Make try! an extended version of std::try!
authorYehuda Katz <wycats@gmail.com>
Sat, 21 Jun 2014 02:18:06 +0000 (19:18 -0700)
committerYehuda Katz <wycats@gmail.com>
Sat, 21 Jun 2014 02:18:06 +0000 (19:18 -0700)
The only caveat to this is that you cannot use try! inside of a function
that return a Result to another function that expects a totally generic
error.

The primary case of this is Encodable/Decodable, which call into
user-specified methods, expecting an `E` back. In these (extremely
unusual) cases, you can use raw_try!.

Of note:

* Once Error lands in core (optimistic much?), Encodable/Decodable can
  be changed to expect an E: Error + FromError<E>.
* This works fine with concrete error types, since FromError maps things
  like IoError to IoError. The only reason it doesn't work with totally
  generic E is that we can't implement FromError<Box<Error>> for
  impl Error and FromError<E> for E.

src/cargo/core/package_id.rs
src/cargo/lib.rs
src/cargo/ops/cargo_read_manifest.rs
src/cargo/ops/cargo_rustc.rs
src/cargo/sources/git/utils.rs
src/cargo/sources/path.rs
src/cargo/util/config.rs
src/cargo/util/errors.rs
src/cargo/util/paths.rs
src/cargo/util/process_builder.rs
src/cargo/util/toml.rs

index f51c5e4365be7fd87a7b41462dbd5b803bf5195f..40a30aadf758dbe6f219d7df13ca9ef80e97ebbd 100644 (file)
@@ -10,6 +10,8 @@ use serialize::{
     Decoder
 };
 
+use util::{CargoError, FromError};
+
 trait ToVersion {
     fn to_version(self) -> Option<semver::Version>;
 }
@@ -92,7 +94,7 @@ impl Show for PackageId {
     }
 }
 
-impl<E, D: Decoder<E>> Decodable<D,E> for PackageId {
+impl<E: CargoError + FromError<E>, D: Decoder<E>> Decodable<D,E> for PackageId {
     fn decode(d: &mut D) -> Result<PackageId, E> {
         let vector: Vec<String> = try!(Decodable::decode(d));
 
index ebdc4415c184fb269a15dd2eddf925158bed08b0..96651618ab798c0e563499df222028f25d54cff3 100644 (file)
@@ -32,7 +32,7 @@ macro_rules! some(
     )
 )
 
-macro_rules! cargo_try (
+macro_rules! try (
     ($expr:expr) => ({
         use util::CargoError;
         match $expr.map_err(|err| err.to_error()) {
@@ -42,6 +42,15 @@ macro_rules! cargo_try (
     })
 )
 
+macro_rules! raw_try (
+    ($expr:expr) => ({
+        match $expr {
+            Ok(val) => val,
+            Err(err) => return Err(err)
+        }
+    })
+)
+
 pub mod core;
 pub mod ops;
 pub mod sources;
index 081907f38d736cf9e8c1fc371fb65aa00768aca5..666de248a0e99e1b253ff2535ec9e3ce797ee3c3 100644 (file)
@@ -15,9 +15,9 @@ 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 = cargo_try!(File::open(path));
-    let data = cargo_try!(file.read_to_end());
-    let (manifest, nested) = cargo_try!(read_manifest(data.as_slice(),
+    let mut file = try!(File::open(path));
+    let data = try!(file.read_to_end());
+    let (manifest, nested) = try!(read_manifest(data.as_slice(),
                                                       source_id));
 
     Ok((Package::new(manifest, path, source_id), nested))
index 14e804c1c7f5fed4d028cb4b5db2f1a3cb701c4f..99ff2cf8ece60c2c4e6eab64453e24e549e0d4fa 100644 (file)
@@ -26,7 +26,7 @@ pub fn compile_packages(pkg: &Package, deps: &PackageSet) -> CargoResult<()> {
     let target_dir = pkg.get_absolute_target_dir();
     let deps_target_dir = target_dir.join("deps");
 
-    let output = cargo_try!(util::process("rustc").arg("-v").exec_with_output());
+    let output = try!(util::process("rustc").arg("-v").exec_with_output());
     let rustc_version = str::from_utf8(output.output.as_slice()).unwrap();
 
     // First ensure that the destination directory exists
@@ -97,7 +97,7 @@ fn compile_pkg(pkg: &Package, cx: &mut Context) -> CargoResult<()> {
 
     // Now that everything has successfully compiled, write our new fingerprint
     // to the relevant location to prevent recompilations in the future.
-    cargo_try!(File::create(&fingerprint_loc).write_str(fingerprint.as_slice()));
+    try!(File::create(&fingerprint_loc).write_str(fingerprint.as_slice()));
     cx.compiled_anything = true;
 
     Ok(())
@@ -111,7 +111,7 @@ fn is_fresh(dep: &Package, loc: &Path,
         Ok(file) => file,
         Err(..) => return Ok((false, new_fingerprint)),
     };
-    let old_fingerprint = cargo_try!(file.read_to_str());
+    let old_fingerprint = try!(file.read_to_str());
 
     log!(5, "old fingerprint: {}", old_fingerprint);
     log!(5, "new fingerprint: {}", new_fingerprint);
index 2b9963a7bdf17e86f5b82a8cab54f6b9b89f1971..761d9401dbf9d83fb94887c6c3d731f4f9fdebe5 100644 (file)
@@ -41,21 +41,21 @@ impl Show for GitReference {
 
 macro_rules! git(
     ($config:expr, $str:expr, $($rest:expr),*) => (
-        cargo_try!(git_inherit(&$config, format!($str, $($rest),*)))
+        try!(git_inherit(&$config, format!($str, $($rest),*)))
     );
 
     ($config:expr, $str:expr) => (
-        cargo_try!(git_inherit(&$config, format!($str)))
+        try!(git_inherit(&$config, format!($str)))
     );
 )
 
 macro_rules! git_output(
     ($config:expr, $str:expr, $($rest:expr),*) => (
-        cargo_try!(git_output(&$config, format!($str, $($rest),*)))
+        try!(git_output(&$config, format!($str, $($rest),*)))
     );
 
     ($config:expr, $str:expr) => (
-        cargo_try!(git_output(&$config, format!($str)))
+        try!(git_output(&$config, format!($str)))
     );
 )
 
@@ -148,9 +148,9 @@ impl GitRemote {
 
     pub fn checkout(&self, into: &Path) -> CargoResult<GitDatabase> {
         if into.exists() {
-            cargo_try!(self.fetch_into(into));
+            try!(self.fetch_into(into));
         } else {
-            cargo_try!(self.clone_into(into));
+            try!(self.clone_into(into));
         }
 
         Ok(GitDatabase { remote: self.clone(), path: into.clone() })
@@ -168,7 +168,7 @@ impl GitRemote {
     fn clone_into(&self, path: &Path) -> CargoResult<()> {
         let dirname = Path::new(path.dirname());
 
-        cargo_try!(mkdir_recursive(path, UserDir));
+        try!(mkdir_recursive(path, UserDir));
 
         Ok(git!(dirname, "clone {} {} --bare --no-hardlinks --quiet",
                 self.fetch_location(), path.display()))
@@ -189,11 +189,11 @@ impl GitDatabase {
 
     pub fn copy_to<S: Str>(&self, reference: S,
                            dest: &Path) -> CargoResult<GitCheckout> {
-        let checkout = cargo_try!(GitCheckout::clone_into(dest, self.clone(),
+        let checkout = try!(GitCheckout::clone_into(dest, self.clone(),
                                   GitReference::for_str(reference.as_slice())));
 
-        cargo_try!(checkout.fetch());
-        cargo_try!(checkout.update_submodules());
+        try!(checkout.fetch());
+        try!(checkout.update_submodules());
 
         Ok(checkout)
     }
@@ -207,7 +207,7 @@ impl GitDatabase {
 impl GitCheckout {
     fn clone_into(into: &Path, database: GitDatabase,
                   reference: GitReference) -> CargoResult<GitCheckout> {
-        let revision = cargo_try!(database.rev_for(reference.as_slice()));
+        let revision = try!(database.rev_for(reference.as_slice()));
         let checkout = GitCheckout {
             location: into.clone(),
             database: database,
@@ -217,7 +217,7 @@ impl GitCheckout {
 
         // If the git checkout already exists, we don't need to clone it again
         if !checkout.location.join(".git").exists() {
-            cargo_try!(checkout.clone_repo());
+            try!(checkout.clone_repo());
         }
 
         Ok(checkout)
@@ -230,13 +230,13 @@ impl GitCheckout {
     fn clone_repo(&self) -> CargoResult<()> {
         let dirname = Path::new(self.location.dirname());
 
-        cargo_try!(mkdir_recursive(&dirname, UserDir).chain_error(|| {
+        try!(mkdir_recursive(&dirname, UserDir).chain_error(|| {
             human(format!("Couldn't mkdir {}",
                           Path::new(self.location.dirname()).display()))
         }));
 
         if self.location.exists() {
-            cargo_try!(rmdir_recursive(&self.location).chain_error(|| {
+            try!(rmdir_recursive(&self.location).chain_error(|| {
                 human(format!("Couldn't rmdir {}",
                               Path::new(&self.location).display()))
             }));
@@ -244,7 +244,7 @@ impl GitCheckout {
 
         git!(dirname, "clone --no-checkout --quiet {} {}",
              self.get_source().display(), self.location.display());
-        cargo_try!(chmod(&self.location, AllPermissions));
+        try!(chmod(&self.location, AllPermissions));
 
         Ok(())
     }
@@ -265,7 +265,7 @@ impl GitCheckout {
              self.get_source().display());
         git!(self.location, "fetch --force --quiet --tags {}",
              self.get_source().display());
-        cargo_try!(self.reset(self.revision.as_slice()));
+        try!(self.reset(self.revision.as_slice()));
         Ok(())
     }
 
@@ -292,7 +292,7 @@ fn git_inherit(path: &Path, str: String) -> CargoResult<()> {
 }
 
 fn git_output(path: &Path, str: String) -> CargoResult<String> {
-    let output = cargo_try!(git(path, str.as_slice()).exec_with_output()
+    let output = try!(git(path, str.as_slice()).exec_with_output()
                                                      .chain_error(||
         human(format!("Executing `git {}` failed", str))));
 
index 6a25349c25d0c2e7b41adec925320f7ff7b5b54e..1f9ec8501a666a5618c02588e321b76f712133c0 100644 (file)
@@ -89,9 +89,9 @@ impl Source for PathSource {
     fn fingerprint(&self) -> CargoResult<String> {
         let mut max = None;
         let target_dir = self.path().join("target");
-        for child in cargo_try!(fs::walk_dir(&self.path())) {
+        for child in try!(fs::walk_dir(&self.path())) {
             if target_dir.is_ancestor_of(&child) { continue }
-            let stat = cargo_try!(fs::stat(&child));
+            let stat = try!(fs::stat(&child));
             max = cmp::max(max, Some(stat.modified));
         }
         match max {
index 603f43c84ef02f3dd39287e4411b0c9b1ff34335..411d3cb1febc8a29cc9280d555b956fd6bf1269c 100644 (file)
@@ -11,7 +11,7 @@ pub struct Config {
 impl Config {
     pub fn new() -> CargoResult<Config> {
         Ok(Config {
-            home_path: cargo_try!(os::homedir().require(|| {
+            home_path: try!(os::homedir().require(|| {
                 human("Couldn't find the home directory")
             }))
         })
@@ -51,10 +51,10 @@ impl<E, S: Encoder<E>> Encodable<S, E> for ConfigValueValue {
     fn encode(&self, s: &mut S) -> Result<(), E> {
         match self {
             &String(ref string) => {
-                try!(string.encode(s));
+                raw_try!(string.encode(s));
             },
             &List(ref list) => {
-                try!(list.encode(s));
+                raw_try!(list.encode(s));
             }
         }
 
@@ -81,8 +81,8 @@ impl ConfigValue {
 impl<E, S: Encoder<E>> Encodable<S, E> for ConfigValue {
     fn encode(&self, s: &mut S) -> Result<(), E> {
         s.emit_map(2, |s| {
-            try!(s.emit_map_elt_key(0, |s| "value".encode(s)));
-            try!(s.emit_map_elt_val(0, |s| self.value.encode(s)));
+            raw_try!(s.emit_map_elt_key(0, |s| "value".encode(s)));
+            raw_try!(s.emit_map_elt_val(0, |s| self.value.encode(s)));
             Ok(())
         })
     }
@@ -105,7 +105,7 @@ pub fn get_config(pwd: Path, key: &str) -> CargoResult<ConfigValue> {
 pub fn all_configs(pwd: Path) -> CargoResult<HashMap<String, ConfigValue>> {
     let mut map = HashMap::new();
 
-    cargo_try!(walk_tree(&pwd, |file| {
+    try!(walk_tree(&pwd, |file| {
         extract_all_configs(file, &mut map)
     }));
 
@@ -119,7 +119,7 @@ fn find_in_tree<T>(pwd: &Path,
     loop {
         let possible = current.join(".cargo").join("config");
         if possible.exists() {
-            let file = cargo_try!(io::fs::File::open(&possible).chain_error(|| {
+            let file = try!(io::fs::File::open(&possible).chain_error(|| {
                 internal("could not open file")
             }));
             match walk(file) {
@@ -142,7 +142,7 @@ fn walk_tree(pwd: &Path,
     loop {
         let possible = current.join(".cargo").join("config");
         if possible.exists() {
-            let file = cargo_try!(io::fs::File::open(&possible).chain_error(|| {
+            let file = try!(io::fs::File::open(&possible).chain_error(|| {
                 internal("could not open file")
             }));
             match walk(file) {
@@ -161,8 +161,8 @@ fn walk_tree(pwd: &Path,
 fn extract_config(file: io::fs::File, key: &str) -> CargoResult<ConfigValue> {
     let path = file.path().clone();
     let mut buf = io::BufferedReader::new(file);
-    let root = cargo_try!(toml::parse_from_buffer(&mut buf));
-    let val = cargo_try!(root.lookup(key).require(|| internal("")));
+    let root = try!(toml::parse_from_buffer(&mut buf));
+    let val = try!(root.lookup(key).require(|| internal("")));
 
     let v = match *val {
         toml::String(ref val) => String(val.clone()),
@@ -179,12 +179,12 @@ fn extract_all_configs(file: io::fs::File,
                        map: &mut HashMap<String, ConfigValue>) -> CargoResult<()> {
     let path = file.path().clone();
     let mut buf = io::BufferedReader::new(file);
-    let root = cargo_try!(toml::parse_from_buffer(&mut buf).chain_error(|| {
+    let root = try!(toml::parse_from_buffer(&mut buf).chain_error(|| {
         internal(format!("could not parse Toml manifest; path={}",
                          path.display()))
     }));
 
-    let table = cargo_try!(root.get_table().require(|| {
+    let table = try!(root.get_table().require(|| {
         internal(format!("could not parse Toml manifest; path={}",
                          path.display()))
     }));
@@ -202,7 +202,7 @@ fn extract_all_configs(file: io::fs::File,
                     ConfigValue { path: vec!(), value: List(vec!()) }
                 });
 
-                cargo_try!(merge_array(config, val.as_slice(),
+                try!(merge_array(config, val.as_slice(),
                                        &path).chain_error(|| {
                     internal(format!("The `{}` key in your config", key))
                 }));
index 37c7aede256e5189ca67a6ef968c1bb92e699a3a..e1dc0aa656ad1510c36ebcedf9c874750987f893 100644 (file)
@@ -64,7 +64,7 @@ macro_rules! from_error (
 
 impl Show for Box<CargoError> {
     fn fmt(&self, f: &mut Formatter) -> fmt::Result {
-        cargo_try!(write!(f, "{}", self.description()));
+        try!(write!(f, "{}", self.description()));
         Ok(())
     }
 }
@@ -156,18 +156,18 @@ impl Show for ProcessError {
             Some(ExitStatus(i)) | Some(ExitSignal(i)) => i.to_str(),
             None => "never executed".to_str()
         };
-        cargo_try!(write!(f, "{} (status={})", self.msg, exit));
+        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 => {
-                        cargo_try!(write!(f, "\n--- stdout\n{}", s));
+                        try!(write!(f, "\n--- stdout\n{}", s));
                     }
                     Some(..) | None => {}
                 }
                 match str::from_utf8(out.error.as_slice()) {
                     Some(s) if s.trim().len() > 0 => {
-                        cargo_try!(write!(f, "\n--- stderr\n{}", s));
+                        try!(write!(f, "\n--- stderr\n{}", s));
                     }
                     Some(..) | None => {}
                 }
index 50fad8b7834f261cfc0d70600b339cdf501c279c..bfdf0ca90465604d1bcd2577a3d2761f463644de 100644 (file)
@@ -27,7 +27,7 @@ pub fn realpath(original: &Path) -> io::IoResult<Path> {
                 Ok(ref stat) if stat.kind != io::TypeSymlink => break,
                 Ok(..) => {
                     followed += 1;
-                    let path = cargo_try!(fs::readlink(&result));
+                    let path = try!(fs::readlink(&result));
                     result.pop();
                     result.push(path);
                 }
index c56eeabc458284281b6e3de6cca48626e5f3b1f8..49e07b9c277c5bda0a6501ba1e23cc077f7a1379 100644 (file)
@@ -17,10 +17,10 @@ pub struct ProcessBuilder {
 
 impl Show for ProcessBuilder {
     fn fmt(&self, f: &mut Formatter) -> fmt::Result {
-        cargo_try!(write!(f, "`{}", self.program));
+        try!(write!(f, "`{}", self.program));
 
         if self.args.len() > 0 {
-            cargo_try!(write!(f, " {}", self.args.connect(" ")));
+            try!(write!(f, " {}", self.args.connect(" ")));
         }
 
         write!(f, "`")
@@ -80,7 +80,7 @@ impl ProcessBuilder {
         let msg = || format!("Could not execute process `{}`",
                              self.debug_string());
 
-        let exit = cargo_try!(command.status().map_err(|_| {
+        let exit = try!(command.status().map_err(|_| {
             process_error(msg(), &command, None, None)
         }));
 
@@ -98,7 +98,7 @@ impl ProcessBuilder {
         let msg = || format!("Could not execute process `{}`",
                              self.debug_string());
 
-        let output = cargo_try!(command.output().map_err(|_| {
+        let output = try!(command.output().map_err(|_| {
             process_error(msg(), &command, None, None)
         }));
 
index bfd7c0ffa6ba30d5bb9d004229479b0983b4a51c..36612ff554abf6847f3f89066819bf1ff5a23e5a 100644 (file)
@@ -11,10 +11,10 @@ use util::{CargoResult, Require, human};
 
 pub fn to_manifest(contents: &[u8],
                    source_id: &SourceId) -> CargoResult<(Manifest, Vec<Path>)> {
-    let root = cargo_try!(toml::parse_from_bytes(contents).map_err(|_| {
+    let root = try!(toml::parse_from_bytes(contents).map_err(|_| {
         human("Cargo.toml is not valid Toml")
     }));
-    let toml = cargo_try!(toml_to_manifest(root).map_err(|_| {
+    let toml = try!(toml_to_manifest(root).map_err(|_| {
         human("Cargo.toml is not a valid manifest")
     }));
 
@@ -33,7 +33,7 @@ fn toml_to_manifest(root: toml::Value) -> CargoResult<TomlManifest> {
         toml::from_toml(root.clone())
     }
 
-    let project = cargo_try!(decode(&root, "project"));
+    let project = try!(decode(&root, "project"));
     let lib = decode(&root, "lib").ok();
     let bin = decode(&root, "bin").ok();
 
@@ -41,7 +41,7 @@ fn toml_to_manifest(root: toml::Value) -> CargoResult<TomlManifest> {
 
     let deps = match deps {
         Some(deps) => {
-            let table = cargo_try!(deps.get_table().require(|| {
+            let table = try!(deps.get_table().require(|| {
                 human("dependencies must be a table")
             })).clone();
 
@@ -56,14 +56,14 @@ fn toml_to_manifest(root: toml::Value) -> CargoResult<TomlManifest> {
                         let mut details = HashMap::<String, String>::new();
 
                         for (k, v) in table.iter() {
-                            let v = cargo_try!(v.get_str().require(|| {
+                            let v = try!(v.get_str().require(|| {
                                 human("dependency values must be string")
                             }));
 
                             details.insert(k.clone(), v.clone());
                         }
 
-                        let version = cargo_try!(details.find_equiv(&"version")
+                        let version = try!(details.find_equiv(&"version")
                                            .require(|| {
                             human("dependencies must include a version")
                         })).clone();
@@ -178,7 +178,7 @@ impl TomlManifest {
                         }
                     };
 
-                    deps.push(cargo_try!(Dependency::parse(n.as_slice(),
+                    deps.push(try!(Dependency::parse(n.as_slice(),
                                                      version.as_slice(),
                                                      &source_id)))
                 }