Add cargo_try!
authorYehuda Katz <wycats@gmail.com>
Thu, 19 Jun 2014 15:13:58 +0000 (08:13 -0700)
committerYehuda Katz <wycats@gmail.com>
Thu, 19 Jun 2014 15:13:58 +0000 (08:13 -0700)
src/cargo/core/manifest.rs
src/cargo/lib.rs
src/cargo/ops/cargo_read_manifest.rs
src/cargo/sources/git/utils.rs
src/cargo/sources/path.rs
src/cargo/util/errors.rs
src/cargo/util/mod.rs
src/cargo/util/toml.rs

index a2cac38f72eb6f295b14869225836018757c8567..f4513b94bca2f043852b484d4ea02747adef0e7d 100644 (file)
@@ -10,7 +10,7 @@ use core::{
     Summary
 };
 use core::dependency::SerializedDependency;
-use util::{CargoResult, box_error};
+use util::{CargoResult, human};
 
 #[deriving(PartialEq,Clone)]
 pub struct Manifest {
@@ -65,7 +65,7 @@ impl LibKind {
             "rlib" => Ok(Rlib),
             "dylib" => Ok(Dylib),
             "staticlib" => Ok(StaticLib),
-            _ => Err(box_error(format!("{} was not one of lib|rlib|dylib|staticlib", string)))
+            _ => Err(human(format!("{} was not one of lib|rlib|dylib|staticlib", string)))
         }
     }
 
index b23b6ce336371eed6a542f2295d6a4c4b89575c2..4952bd7eb2779a25e1910469371374a0791bb5f0 100644 (file)
@@ -30,6 +30,13 @@ macro_rules! some(
     }
   ))
 
+macro_rules! cargo_try (
+    ($expr:expr) => ({
+        use util::BoxError;
+        try!($expr.box_error())
+    })
+)
+
 pub mod core;
 pub mod ops;
 pub mod sources;
index f5524618e37895a40fbc09ef93866d5d10ef7030..258b1cd11aef69e6be8ba87050c5fcb7ed8635ff 100644 (file)
@@ -1,7 +1,7 @@
 use std::io::File;
 use util;
 use core::{Package,Manifest,SourceId};
-use util::{CargoResult, box_error, human};
+use util::{CargoResult, human};
 
 pub fn read_manifest(contents: &[u8], source_id: &SourceId) -> CargoResult<(Manifest, Vec<Path>)> {
     util::toml::to_manifest(contents, source_id).map_err(human)
@@ -9,9 +9,9 @@ pub fn read_manifest(contents: &[u8], source_id: &SourceId) -> CargoResult<(Mani
 
 pub fn read_package(path: &Path, source_id: &SourceId) -> CargoResult<(Package, Vec<Path>)> {
     log!(5, "read_package; path={}; source-id={}", path.display(), source_id);
-    let mut file = try!(File::open(path).map_err(box_error));
-    let data = try!(file.read_to_end().map_err(box_error));
-    let (manifest, nested) = try!(read_manifest(data.as_slice(), source_id));
+    let mut file = cargo_try!(File::open(path));
+    let data = cargo_try!(file.read_to_end());
+    let (manifest, nested) = cargo_try!(read_manifest(data.as_slice(), source_id));
 
     Ok((Package::new(manifest, path), nested))
 }
index c1fbc4edfc4e85acf8794074853e72a9b15163bd..d3e3ae8520b96c455c04f679734af3a1cc9580a5 100644 (file)
@@ -1,5 +1,5 @@
 use url::Url;
-use util::{CargoResult, ProcessBuilder, process, box_error};
+use util::{CargoResult, ChainError, ProcessBuilder, process};
 use std::fmt;
 use std::fmt::{Show,Formatter};
 use std::str;
@@ -41,21 +41,21 @@ impl Show for GitReference {
 
 macro_rules! git(
     ($config:expr, $str:expr, $($rest:expr),*) => (
-        try!(git_inherit(&$config, format!($str, $($rest),*)))
+        cargo_try!(git_inherit(&$config, format!($str, $($rest),*)))
     );
 
     ($config:expr, $str:expr) => (
-        try!(git_inherit(&$config, format!($str)))
+        cargo_try!(git_inherit(&$config, format!($str)))
     );
 )
 
 macro_rules! git_output(
     ($config:expr, $str:expr, $($rest:expr),*) => (
-        try!(git_output(&$config, format!($str, $($rest),*)))
+        cargo_try!(git_output(&$config, format!($str, $($rest),*)))
     );
 
     ($config:expr, $str:expr) => (
-        try!(git_output(&$config, format!($str)))
+        cargo_try!(git_output(&$config, format!($str)))
     );
 )
 
@@ -158,9 +158,9 @@ impl GitRemote {
 
     pub fn checkout(&self, into: &Path) -> CargoResult<GitDatabase> {
         if into.exists() {
-            try!(self.fetch_into(into));
+            cargo_try!(self.fetch_into(into));
         } else {
-            try!(self.clone_into(into));
+            cargo_try!(self.clone_into(into));
         }
 
         Ok(GitDatabase { remote: self.clone(), path: into.clone() })
@@ -173,7 +173,7 @@ impl GitRemote {
     fn clone_into(&self, path: &Path) -> CargoResult<()> {
         let dirname = Path::new(path.dirname());
 
-        try!(mkdir_recursive(path, UserDir).map_err(box_error));
+        cargo_try!(mkdir_recursive(path, UserDir));
 
         Ok(git!(dirname, "clone {} {} --bare --no-hardlinks --quiet", self.fetch_location(), path.display()))
     }
@@ -192,10 +192,10 @@ impl GitDatabase {
     }
 
     pub fn copy_to<S: Str>(&self, reference: S, dest: &Path) -> CargoResult<GitCheckout> {
-        let checkout = try!(GitCheckout::clone_into(dest, self.clone(), GitReference::for_str(reference.as_slice())));
+        let checkout = cargo_try!(GitCheckout::clone_into(dest, self.clone(), GitReference::for_str(reference.as_slice())));
 
-        try!(checkout.fetch());
-        try!(checkout.update_submodules());
+        cargo_try!(checkout.fetch());
+        cargo_try!(checkout.update_submodules());
 
         Ok(checkout)
     }
@@ -208,12 +208,12 @@ impl GitDatabase {
 
 impl GitCheckout {
     fn clone_into(into: &Path, database: GitDatabase, reference: GitReference) -> CargoResult<GitCheckout> {
-        let revision = try!(database.rev_for(reference.as_slice()));
+        let revision = cargo_try!(database.rev_for(reference.as_slice()));
         let checkout = GitCheckout { location: into.clone(), database: database, reference: reference, revision: revision };
 
         // If the git checkout already exists, we don't need to clone it again
         if !checkout.location.join(".git").exists() {
-            try!(checkout.clone_repo());
+            cargo_try!(checkout.clone_repo());
         }
 
         Ok(checkout)
@@ -226,23 +226,23 @@ impl GitCheckout {
     fn clone_repo(&self) -> CargoResult<()> {
         let dirname = Path::new(self.location.dirname());
 
-        try!(mkdir_recursive(&dirname, UserDir).map_err(|_|
-            box_error(format!("Couldn't mkdir {}", Path::new(self.location.dirname()).display()))));
+        cargo_try!(mkdir_recursive(&dirname, UserDir).chain_error(||
+            format!("Couldn't mkdir {}", Path::new(self.location.dirname()).display())));
 
         if self.location.exists() {
-            try!(rmdir_recursive(&self.location).map_err(|_|
-                box_error(format!("Couldn't rmdir {}", Path::new(&self.location).display()))));
+            cargo_try!(rmdir_recursive(&self.location).chain_error(||
+                format!("Couldn't rmdir {}", Path::new(&self.location).display())));
         }
 
         git!(dirname, "clone --no-checkout --quiet {} {}", self.get_source().display(), self.location.display());
-        try!(chmod(&self.location, AllPermissions).map_err(box_error));
+        cargo_try!(chmod(&self.location, AllPermissions));
 
         Ok(())
     }
 
     fn fetch(&self) -> CargoResult<()> {
         git!(self.location, "fetch --force --quiet --tags {}", self.get_source().display());
-        try!(self.reset(self.revision.as_slice()));
+        cargo_try!(self.reset(self.revision.as_slice()));
         Ok(())
     }
 
@@ -262,13 +262,12 @@ fn git(path: &Path, str: &str) -> ProcessBuilder {
 }
 
 fn git_inherit(path: &Path, str: String) -> CargoResult<()> {
-    git(path, str.as_slice()).exec().map_err(|err|
-        box_error(format!("Executing `git {}` failed: {}", str, err)))
+    git(path, str.as_slice()).exec().chain_error(|| format!("Executing `git {}` failed", str))
 }
 
 fn git_output(path: &Path, str: String) -> CargoResult<String> {
-    let output = try!(git(path, str.as_slice()).exec_with_output().map_err(|_|
-        box_error(format!("Executing `git {}` failed", str))));
+    let output = cargo_try!(git(path, str.as_slice()).exec_with_output().chain_error(||
+        format!("Executing `git {}` failed", str)));
 
     Ok(to_str(output.output.as_slice()).as_slice().trim_right().to_str())
 }
index 7aa292f188b00f452de796ca5b6f17c97e7de8a2..d60a5fa06b0f7d561e31fdd87f8c8cd9dc83902c 100644 (file)
@@ -2,7 +2,7 @@ use std::fmt;
 use std::fmt::{Show,Formatter};
 use core::{Package,PackageId,Summary,SourceId,Source};
 use ops;
-use util::{CargoResult, box_error};
+use util::{CargoResult, error};
 
 pub struct PathSource {
     id: SourceId,
@@ -40,12 +40,12 @@ impl PathSource {
         log!(5, "get_root_package; source={}", self);
 
         if !self.updated {
-            return Err(box_error("source has not been updated"))
+            return Err(error("source has not been updated"))
         }
 
         match self.packages.as_slice().head() {
             Some(pkg) => Ok(pkg.clone()),
-            None => Err(box_error("no package found in source"))
+            None => Err(error("no package found in source"))
         }
     }
 }
index 8c9187d4f53b275da6c93bb6ecf2087f34de045e..707c9aa3063213d6fb78fc5ebf6880611998e011 100644 (file)
@@ -11,6 +11,10 @@ pub trait CargoError {
     fn cause<'a>(&'a self) -> Option<&'a CargoError> { None }
     fn is_human(&self) -> bool { false }
 
+    fn box_error(self) -> Box<CargoError> {
+        box self as Box<CargoError>
+    }
+
     fn concrete(&self) -> ConcreteCargoError {
         ConcreteCargoError {
             description: self.description(),
@@ -45,10 +49,38 @@ impl CargoError for Box<CargoError> {
     fn is_human(&self) -> bool {
         (*self).is_human()
     }
+
+    fn box_error(self) -> Box<CargoError> {
+        self
+    }
 }
 
 pub type CargoResult<T> = Result<T, Box<CargoError>>;
 
+pub trait BoxError<T> {
+    fn box_error(self) -> CargoResult<T>;
+}
+
+pub trait ChainError<T> {
+    fn chain_error<E: CargoError>(self, callback: || -> E) -> CargoResult<T> ;
+}
+
+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| {
+            let mut update = callback().concrete();
+            update.cause = Some(err.box_error());
+            box update as Box<CargoError>
+        })
+    }
+}
+
 impl CargoError for &'static str {
     fn description(&self) -> String { self.to_str() }
     fn is_human(&self) -> bool { true }
@@ -200,7 +232,3 @@ pub fn chain<E: CargoError>(original: Box<CargoError>, update: E) -> Box<CargoEr
     concrete.cause = Some(original);
     box concrete as Box<CargoError>
 }
-
-pub fn box_error<S: CargoError + 'static>(err: S) -> Box<CargoError> {
-    box err as Box<CargoError>
-}
index 8957948c991cb0822ddcc7f865ad571152ba1b36..1de113644a5c3d0094f27c108b6703e197e996e5 100644 (file)
@@ -1,8 +1,8 @@
 pub use self::config::Config;
 pub use self::process_builder::{process,ProcessBuilder};
 pub use self::result::{Wrap, Require};
-pub use self::errors::{CargoResult, CargoError, CliResult, CliError, ProcessError};
-pub use self::errors::{process_error, box_error, internal_error, error, human, chain};
+pub use self::errors::{CargoResult, CargoError, BoxError, ChainError, CliResult, CliError, ProcessError};
+pub use self::errors::{process_error, internal_error, error, human, chain};
 pub use self::paths::realpath;
 
 pub mod graph;
index 261b9413b89ce2eeb612595605030c6d9a909793..22898713f56ab08ac79cf8791b7529687ad84c79 100644 (file)
@@ -7,7 +7,7 @@ use serialize::Decodable;
 use core::{SourceId,GitKind};
 use core::manifest::{LibKind,Lib};
 use core::{Summary,Manifest,Target,Dependency,PackageId};
-use util::{CargoResult, Require, error, box_error};
+use util::{CargoResult, Require, error};
 
 pub fn to_manifest(contents: &[u8], source_id: &SourceId) -> CargoResult<(Manifest, Vec<Path>)> {
     let root = try!(toml::parse_from_bytes(contents).map_err(|_| error("Cargo.toml is not valid Toml")));
@@ -25,7 +25,7 @@ fn toml_to_manifest(root: toml::Value) -> CargoResult<TomlManifest> {
         toml::from_toml(root.clone())
     }
 
-    let project = try!(decode(&root, "project").map_err(box_error));
+    let project = cargo_try!(decode(&root, "project"));
     let lib = decode(&root, "lib").ok();
     let bin = decode(&root, "bin").ok();