Switch from try! to ?

Josh Triplett created

Change summary

src/main.rs | 464 +++++++++++++++++++++++++++---------------------------
1 file changed, 232 insertions(+), 232 deletions(-)

Detailed changes

src/main.rs 🔗

@@ -101,24 +101,24 @@ const GIT_FILEMODE_BLOB: u32 = 0o100644;
 const GIT_FILEMODE_COMMIT: u32 = 0o160000;
 
 fn commit_obj_summarize_components(commit: &mut Commit) -> Result<(String, String)> {
-    let short_id_buf = try!(commit.as_object().short_id());
+    let short_id_buf = commit.as_object().short_id()?;
     let short_id = short_id_buf.as_str().unwrap();
     let summary = String::from_utf8_lossy(commit.summary_bytes().unwrap());
     Ok((short_id.to_string(), summary.to_string()))
 }
 
 fn commit_summarize_components(repo: &Repository, id: Oid) -> Result<(String, String)> {
-    let mut commit = try!(repo.find_commit(id));
+    let mut commit = repo.find_commit(id)?;
     commit_obj_summarize_components(&mut commit)
 }
 
 fn commit_obj_summarize(commit: &mut Commit) -> Result<String> {
-    let (short_id, summary) = try!(commit_obj_summarize_components(commit));
+    let (short_id, summary) = commit_obj_summarize_components(commit)?;
     Ok(format!("{} {}", short_id, summary))
 }
 
 fn commit_summarize(repo: &Repository, id: Oid) -> Result<String> {
-    let mut commit = try!(repo.find_commit(id));
+    let mut commit = repo.find_commit(id)?;
     commit_obj_summarize(&mut commit)
 }
 
@@ -133,16 +133,16 @@ fn notfound_to_none<T>(result: std::result::Result<T, git2::Error>) -> Result<Op
 // If current_id_opt is Some, acts like reference_matching.  If current_id_opt is None, acts like
 // reference.
 fn reference_matching_opt<'repo>(repo: &'repo Repository, name: &str, id: Oid, force: bool, current_id_opt: Option<Oid>, log_message: &str) -> Result<Reference<'repo>> {
-    match current_id_opt {
-        None => Ok(try!(repo.reference(name, id, force, log_message))),
-        Some(current_id) => Ok(try!(repo.reference_matching(name, id, force, current_id, log_message))),
-    }
+    Ok(match current_id_opt {
+        None => repo.reference(name, id, force, log_message)?,
+        Some(current_id) => repo.reference_matching(name, id, force, current_id, log_message)?,
+    })
 }
 
 fn parents_from_ids(repo: &Repository, mut parents: Vec<Oid>) -> Result<Vec<Commit>> {
     parents.sort();
     parents.dedup();
-    parents.drain(..).map(|id| Ok(try!(repo.find_commit(id)))).collect::<Result<Vec<Commit>>>()
+    parents.drain(..).map(|id| Ok(repo.find_commit(id)?)).collect::<Result<Vec<Commit>>>()
 }
 
 struct Internals<'repo> {
@@ -152,35 +152,35 @@ struct Internals<'repo> {
 
 impl<'repo> Internals<'repo> {
     fn read(repo: &'repo Repository) -> Result<Self> {
-        let shead = try!(repo.find_reference(SHEAD_REF));
-        let series_name = try!(shead_series_name(&shead));
-        let mut internals = try!(Internals::read_series(repo, &series_name));
-        try!(internals.update_series(repo));
+        let shead = repo.find_reference(SHEAD_REF)?;
+        let series_name = shead_series_name(&shead)?;
+        let mut internals = Internals::read_series(repo, &series_name)?;
+        internals.update_series(repo)?;
         Ok(internals)
     }
 
     fn read_series(repo: &'repo Repository, series_name: &str) -> Result<Self> {
-        let committed_id = try!(notfound_to_none(repo.refname_to_id(&format!("{}{}", SERIES_PREFIX, series_name))));
+        let committed_id = notfound_to_none(repo.refname_to_id(&format!("{}{}", SERIES_PREFIX, series_name)))?;
         let maybe_get_ref = |prefix: &str| -> Result<TreeBuilder<'repo>> {
-            match try!(notfound_to_none(repo.refname_to_id(&format!("{}{}", prefix, series_name)))).or(committed_id) {
+            match notfound_to_none(repo.refname_to_id(&format!("{}{}", prefix, series_name)))?.or(committed_id) {
                 Some(id) => {
-                    let c = try!(repo.find_commit(id));
-                    let t = try!(c.tree());
-                    Ok(try!(repo.treebuilder(Some(&t))))
+                    let c = repo.find_commit(id)?;
+                    let t = c.tree()?;
+                    Ok(repo.treebuilder(Some(&t))?)
                 }
-                None => Ok(try!(repo.treebuilder(None))),
+                None => Ok(repo.treebuilder(None)?),
             }
         };
         Ok(Internals {
-            staged: try!(maybe_get_ref(STAGED_PREFIX)),
-            working: try!(maybe_get_ref(WORKING_PREFIX)),
+            staged: maybe_get_ref(STAGED_PREFIX)?,
+            working: maybe_get_ref(WORKING_PREFIX)?,
         })
     }
 
     fn exists(repo: &'repo Repository, series_name: &str) -> Result<bool> {
         for prefix in [SERIES_PREFIX, STAGED_PREFIX, WORKING_PREFIX].iter() {
             let prefixed_name = format!("{}{}", prefix, series_name);
-            if try!(notfound_to_none(repo.refname_to_id(&prefixed_name))).is_some() {
+            if notfound_to_none(repo.refname_to_id(&prefixed_name))?.is_some() {
                 return Ok(true);
             }
         }
@@ -192,10 +192,10 @@ impl<'repo> Internals<'repo> {
         let mut copied_any = false;
         for prefix in [SERIES_PREFIX, STAGED_PREFIX, WORKING_PREFIX].iter() {
             let prefixed_source = format!("{}{}", prefix, source);
-            if let Some(r) = try!(notfound_to_none(repo.find_reference(&prefixed_source))) {
-                let oid = try!(r.target().ok_or(format!("Internal error: \"{}\" is a symbolic reference", prefixed_source)));
+            if let Some(r) = notfound_to_none(repo.find_reference(&prefixed_source))? {
+                let oid = r.target().ok_or(format!("Internal error: \"{}\" is a symbolic reference", prefixed_source))?;
                 let prefixed_dest = format!("{}{}", prefix, dest);
-                try!(repo.reference(&prefixed_dest, oid, false, &format!("copied from {}", prefixed_source)));
+                repo.reference(&prefixed_dest, oid, false, &format!("copied from {}", prefixed_source))?;
                 copied_any = true;
             }
         }
@@ -207,8 +207,8 @@ impl<'repo> Internals<'repo> {
         let mut deleted_any = false;
         for prefix in [SERIES_PREFIX, STAGED_PREFIX, WORKING_PREFIX].iter() {
             let prefixed_name = format!("{}{}", prefix, series_name);
-            if let Some(mut r) = try!(notfound_to_none(repo.find_reference(&prefixed_name))) {
-                try!(r.delete());
+            if let Some(mut r) = notfound_to_none(repo.find_reference(&prefixed_name))? {
+                r.delete()?;
                 deleted_any = true;
             }
         }
@@ -216,29 +216,29 @@ impl<'repo> Internals<'repo> {
     }
 
     fn update_series(&mut self, repo: &'repo Repository) -> Result<()> {
-        let head_id = try!(repo.refname_to_id("HEAD"));
-        try!(self.working.insert("series", head_id, GIT_FILEMODE_COMMIT as i32));
+        let head_id = repo.refname_to_id("HEAD")?;
+        self.working.insert("series", head_id, GIT_FILEMODE_COMMIT as i32)?;
         Ok(())
     }
 
     fn write(&self, repo: &'repo Repository) -> Result<()> {
-        let config = try!(repo.config());
-        let author = try!(get_signature(&config, "AUTHOR"));
-        let committer = try!(get_signature(&config, "COMMITTER"));
+        let config = repo.config()?;
+        let author = get_signature(&config, "AUTHOR")?;
+        let committer = get_signature(&config, "COMMITTER")?;
 
-        let shead = try!(repo.find_reference(SHEAD_REF));
-        let series_name = try!(shead_series_name(&shead));
+        let shead = repo.find_reference(SHEAD_REF)?;
+        let series_name = shead_series_name(&shead)?;
         let maybe_commit = |prefix: &str, tb: &TreeBuilder| -> Result<()> {
-            let tree_id = try!(tb.write());
+            let tree_id = tb.write()?;
             let refname = format!("{}{}", prefix, series_name);
-            let old_commit_id = try!(notfound_to_none(repo.refname_to_id(&refname)));
+            let old_commit_id = notfound_to_none(repo.refname_to_id(&refname))?;
             if let Some(id) = old_commit_id {
-                let c = try!(repo.find_commit(id));
+                let c = repo.find_commit(id)?;
                 if c.tree_id() == tree_id {
                     return Ok(());
                 }
             }
-            let tree = try!(repo.find_tree(tree_id));
+            let tree = repo.find_tree(tree_id)?;
             let mut parents = Vec::new();
             // Include all commits from tree, to keep them reachable and fetchable. Include base,
             // because series might not have it as an ancestor; we don't enforce that until commit.
@@ -247,15 +247,15 @@ impl<'repo> Internals<'repo> {
                     parents.push(e.id());
                 }
             }
-            let parents = try!(parents_from_ids(repo, parents));
+            let parents = parents_from_ids(repo, parents)?;
             let parents_ref: Vec<&_> = parents.iter().collect();
-            let commit_id = try!(repo.commit(None, &author, &committer, &refname, &tree, &parents_ref));
-            try!(repo.reference_ensure_log(&refname));
-            try!(reference_matching_opt(repo, &refname, commit_id, true, old_commit_id, &format!("commit: {}", refname)));
+            let commit_id = repo.commit(None, &author, &committer, &refname, &tree, &parents_ref)?;
+            repo.reference_ensure_log(&refname)?;
+            reference_matching_opt(repo, &refname, commit_id, true, old_commit_id, &format!("commit: {}", refname))?;
             Ok(())
         };
-        try!(maybe_commit(STAGED_PREFIX, &self.staged));
-        try!(maybe_commit(WORKING_PREFIX, &self.working));
+        maybe_commit(STAGED_PREFIX, &self.staged)?;
+        maybe_commit(WORKING_PREFIX, &self.working)?;
         Ok(())
     }
 }
@@ -265,13 +265,13 @@ fn diff_empty(diff: &Diff) -> bool {
 }
 
 fn add(repo: &Repository, m: &ArgMatches) -> Result<()> {
-    let mut internals = try!(Internals::read(repo));
+    let mut internals = Internals::read(repo)?;
     for file in m.values_of_os("change").unwrap() {
-        match try!(internals.working.get(file)) {
-            Some(entry) => { try!(internals.staged.insert(file, entry.id(), entry.filemode())); }
+        match internals.working.get(file)? {
+            Some(entry) => { internals.staged.insert(file, entry.id(), entry.filemode())?; }
             None => {
-                if try!(internals.staged.get(file)).is_some() {
-                    try!(internals.staged.remove(file));
+                if internals.staged.get(file)?.is_some() {
+                    internals.staged.remove(file)?;
                 }
             }
         }
@@ -280,35 +280,35 @@ fn add(repo: &Repository, m: &ArgMatches) -> Result<()> {
 }
 
 fn unadd(repo: &Repository, m: &ArgMatches) -> Result<()> {
-    let shead = try!(repo.find_reference(SHEAD_REF));
+    let shead = repo.find_reference(SHEAD_REF)?;
     let started = {
-        let shead_target = try!(shead.symbolic_target().ok_or("SHEAD not a symbolic reference"));
-        try!(notfound_to_none(repo.find_reference(shead_target))).is_some()
+        let shead_target = shead.symbolic_target().ok_or("SHEAD not a symbolic reference")?;
+        notfound_to_none(repo.find_reference(shead_target))?.is_some()
     };
 
-    let mut internals = try!(Internals::read(repo));
+    let mut internals = Internals::read(repo)?;
     if started {
-        let shead_commit = try!(shead.peel_to_commit());
-        let shead_tree = try!(shead_commit.tree());
+        let shead_commit = shead.peel_to_commit()?;
+        let shead_tree = shead_commit.tree()?;
 
         for file in m.values_of("change").unwrap() {
             match shead_tree.get_name(file) {
                 Some(entry) => {
-                    try!(internals.staged.insert(file, entry.id(), entry.filemode()));
+                    internals.staged.insert(file, entry.id(), entry.filemode())?;
                 }
-                None => { try!(internals.staged.remove(file)); }
+                None => { internals.staged.remove(file)?; }
             }
         }
     } else {
         for file in m.values_of("change").unwrap() {
-            try!(internals.staged.remove(file))
+            internals.staged.remove(file)?
         }
     }
     internals.write(repo)
 }
 
 fn shead_series_name(shead: &Reference) -> Result<String> {
-    let shead_target = try!(shead.symbolic_target().ok_or("SHEAD not a symbolic reference"));
+    let shead_target = shead.symbolic_target().ok_or("SHEAD not a symbolic reference")?;
     if !shead_target.starts_with(SERIES_PREFIX) {
         return Err(format!("SHEAD does not start with {}", SERIES_PREFIX).into());
     }
@@ -319,12 +319,12 @@ fn series(out: &mut Output, repo: &Repository) -> Result<()> {
     let mut refs = Vec::new();
     for prefix in [SERIES_PREFIX, STAGED_PREFIX, WORKING_PREFIX].iter() {
         let l = prefix.len();
-        for r in try!(repo.references_glob(&[prefix, "*"].concat())).names() {
-            refs.push(try!(r)[l..].to_string());
+        for r in repo.references_glob(&[prefix, "*"].concat())?.names() {
+            refs.push(r?[l..].to_string());
         }
     }
-    let shead_target = if let Some(shead) = try!(notfound_to_none(repo.find_reference(SHEAD_REF))) {
-        Some(try!(shead_series_name(&shead)))
+    let shead_target = if let Some(shead) = notfound_to_none(repo.find_reference(SHEAD_REF))? {
+        Some(shead_series_name(&shead)?)
     } else {
         None
     };
@@ -332,47 +332,47 @@ fn series(out: &mut Output, repo: &Repository) -> Result<()> {
     refs.sort();
     refs.dedup();
 
-    let config = try!(try!(repo.config()).snapshot());
-    try!(out.auto_pager(&config, "branch", false));
-    let color_current = try!(out.get_color(&config, "branch", "current", "green"));
-    let color_plain = try!(out.get_color(&config, "branch", "plain", "normal"));
+    let config = repo.config()?.snapshot()?;
+    out.auto_pager(&config, "branch", false)?;
+    let color_current = out.get_color(&config, "branch", "current", "green")?;
+    let color_plain = out.get_color(&config, "branch", "plain", "normal")?;
     for name in refs.iter() {
         let (star, color) = if Some(name) == shead_target.as_ref() {
             ('*', color_current)
         } else {
             (' ', color_plain)
         };
-        let new = if try!(notfound_to_none(repo.refname_to_id(&format!("{}{}", SERIES_PREFIX, name)))).is_none() {
+        let new = if notfound_to_none(repo.refname_to_id(&format!("{}{}", SERIES_PREFIX, name)))?.is_none() {
             " (new, no commits yet)"
         } else {
             ""
         };
-        try!(writeln!(out, "{} {}{}", star, color.paint(name as &str), new));
+        writeln!(out, "{} {}{}", star, color.paint(name as &str), new)?;
     }
     if refs.is_empty() {
-        try!(writeln!(out, "No series; use \"git series start <name>\" to start"));
+        writeln!(out, "No series; use \"git series start <name>\" to start")?;
     }
     Ok(())
 }
 
 fn start(repo: &Repository, m: &ArgMatches) -> Result<()> {
-    let head = try!(repo.head());
-    let head_commit = try!(head.peel_to_commit());
+    let head = repo.head()?;
+    let head_commit = head.peel_to_commit()?;
     let head_id = head_commit.as_object().id();
 
     let name = m.value_of("name").unwrap();
-    if try!(Internals::exists(repo, name)) {
+    if Internals::exists(repo, name)? {
         return Err(format!("Series {} already exists.\nUse checkout to resume working on an existing patch series.", name).into());
     }
     let prefixed_name = &[SERIES_PREFIX, name].concat();
-    try!(repo.reference_symbolic(SHEAD_REF, &prefixed_name, true, &format!("git series start {}", name)));
+    repo.reference_symbolic(SHEAD_REF, &prefixed_name, true, &format!("git series start {}", name))?;
 
-    let internals = try!(Internals::read(repo));
-    try!(internals.write(repo));
+    let internals = Internals::read(repo)?;
+    internals.write(repo)?;
 
     // git status parses this reflog string; the prefix must remain "checkout: moving from ".
-    try!(repo.reference("HEAD", head_id, true, &format!("checkout: moving from {} to {} (git series start {})", head_id, head_id, name)));
-    println!("HEAD is now detached at {}", try!(commit_summarize(&repo, head_id)));
+    repo.reference("HEAD", head_id, true, &format!("checkout: moving from {} to {} (git series start {})", head_id, head_id, name))?;
+    println!("HEAD is now detached at {}", commit_summarize(&repo, head_id)?);
     Ok(())
 }
 
@@ -410,7 +410,7 @@ fn checkout_tree(repo: &Repository, treeish: &Object) -> Result<()> {
             writeln!(msg, "Please, commit your changes or stash them before you switch series.").unwrap();
             return Err(msg.into());
         }
-        _ => try!(result),
+        _ => result?,
     }
     println!("");
     if !dirty.is_empty() {
@@ -428,36 +428,36 @@ fn checkout(repo: &Repository, m: &ArgMatches) -> Result<()> {
         s => { return Err(format!("{:?} in progress; cannot checkout patch series", s).into()); }
     }
     let name = m.value_of("name").unwrap();
-    if !try!(Internals::exists(repo, name)) {
+    if !Internals::exists(repo, name)? {
         return Err(format!("Series {} does not exist.\nUse \"git series start <name>\" to start a new patch series.", name).into());
     }
 
-    let internals = try!(Internals::read_series(repo, name));
-    let new_head_id = try!(try!(internals.working.get("series")).ok_or(format!("Could not find \"series\" in \"{}\"", name))).id();
-    let new_head = try!(repo.find_commit(new_head_id)).into_object();
+    let internals = Internals::read_series(repo, name)?;
+    let new_head_id = internals.working.get("series")?.ok_or(format!("Could not find \"series\" in \"{}\"", name))?.id();
+    let new_head = repo.find_commit(new_head_id)?.into_object();
 
-    try!(checkout_tree(repo, &new_head));
+    checkout_tree(repo, &new_head)?;
 
-    let head = try!(repo.head());
-    let head_commit = try!(head.peel_to_commit());
+    let head = repo.head()?;
+    let head_commit = head.peel_to_commit()?;
     let head_id = head_commit.as_object().id();
-    println!("Previous HEAD position was {}", try!(commit_summarize(&repo, head_id)));
+    println!("Previous HEAD position was {}", commit_summarize(&repo, head_id)?);
 
     let prefixed_name = &[SERIES_PREFIX, name].concat();
-    try!(repo.reference_symbolic(SHEAD_REF, &prefixed_name, true, &format!("git series checkout {}", name)));
-    try!(internals.write(repo));
+    repo.reference_symbolic(SHEAD_REF, &prefixed_name, true, &format!("git series checkout {}", name))?;
+    internals.write(repo)?;
 
     // git status parses this reflog string; the prefix must remain "checkout: moving from ".
-    try!(repo.reference("HEAD", new_head_id, true, &format!("checkout: moving from {} to {} (git series checkout {})", head_id, new_head_id, name)));
-    println!("HEAD is now detached at {}", try!(commit_summarize(&repo, new_head_id)));
+    repo.reference("HEAD", new_head_id, true, &format!("checkout: moving from {} to {} (git series checkout {})", head_id, new_head_id, name))?;
+    println!("HEAD is now detached at {}", commit_summarize(&repo, new_head_id)?);
 
     Ok(())
 }
 
 fn base(repo: &Repository, m: &ArgMatches) -> Result<()> {
-    let mut internals = try!(Internals::read(repo));
+    let mut internals = Internals::read(repo)?;
 
-    let current_base_id = match try!(internals.working.get("base")) {
+    let current_base_id = match internals.working.get("base")? {
         Some(entry) => entry.id(),
         _ => Oid::zero(),
     };
@@ -475,11 +475,11 @@ fn base(repo: &Repository, m: &ArgMatches) -> Result<()> {
         Oid::zero()
     } else {
         let base = m.value_of("base").unwrap();
-        let base_object = try!(repo.revparse_single(base));
-        let base_commit = try!(base_object.peel(ObjectType::Commit));
+        let base_object = repo.revparse_single(base)?;
+        let base_commit = base_object.peel(ObjectType::Commit)?;
         let base_id = base_commit.id();
-        let s_working_series = try!(try!(internals.working.get("series")).ok_or("Could not find entry \"series\" in working vesion of current series"));
-        if base_id != s_working_series.id() && !try!(repo.graph_descendant_of(s_working_series.id(), base_id)) {
+        let s_working_series = internals.working.get("series")?.ok_or("Could not find entry \"series\" in working vesion of current series")?;
+        if base_id != s_working_series.id() && !repo.graph_descendant_of(s_working_series.id(), base_id)? {
             return Err(format!("Cannot set base to {}: not an ancestor of the patch series {}", base, s_working_series.id()).into());
         }
         base_id
@@ -491,17 +491,17 @@ fn base(repo: &Repository, m: &ArgMatches) -> Result<()> {
     }
 
     if !current_base_id.is_zero() {
-        println!("Previous base was {}", try!(commit_summarize(&repo, current_base_id)));
+        println!("Previous base was {}", commit_summarize(&repo, current_base_id)?);
     }
 
     if new_base_id.is_zero() {
-        try!(internals.working.remove("base"));
-        try!(internals.write(repo));
+        internals.working.remove("base")?;
+        internals.write(repo)?;
         println!("Cleared patch series base");
     } else {
-        try!(internals.working.insert("base", new_base_id, GIT_FILEMODE_COMMIT as i32));
-        try!(internals.write(repo));
-        println!("Set patch series base to {}", try!(commit_summarize(&repo, new_base_id)));
+        internals.working.insert("base", new_base_id, GIT_FILEMODE_COMMIT as i32)?;
+        internals.write(repo)?;
+        println!("Set patch series base to {}", commit_summarize(&repo, new_base_id)?);
     }
 
     Ok(())
@@ -509,7 +509,7 @@ fn base(repo: &Repository, m: &ArgMatches) -> Result<()> {
 
 fn detach(repo: &Repository) -> Result<()> {
     match repo.find_reference(SHEAD_REF) {
-        Ok(mut r) => try!(r.delete()),
+        Ok(mut r) => r.delete()?,
         Err(_) => { return Err("No current patch series to detach from.".into()); }
     }
     Ok(())
@@ -518,25 +518,25 @@ fn detach(repo: &Repository) -> Result<()> {
 fn delete(repo: &Repository, m: &ArgMatches) -> Result<()> {
     let name = m.value_of("name").unwrap();
     if let Ok(shead) = repo.find_reference(SHEAD_REF) {
-        let shead_target = try!(shead_series_name(&shead));
+        let shead_target = shead_series_name(&shead)?;
         if shead_target == name {
             return Err(format!("Cannot delete the current series \"{}\"; detach first.", name).into());
         }
     }
-    if !try!(Internals::delete(repo, name)) {
+    if Internals::delete(repo, name)? == false {
         return Err(format!("Nothing to delete: series \"{}\" does not exist.", name).into());
     }
     Ok(())
 }
 
 fn do_diff(out: &mut Output, repo: &Repository) -> Result<()> {
-    let internals = try!(Internals::read(&repo));
-    let config = try!(try!(repo.config()).snapshot());
-    try!(out.auto_pager(&config, "diff", true));
-    let diffcolors = try!(DiffColors::new(out, &config));
+    let internals = Internals::read(&repo)?;
+    let config = repo.config()?.snapshot()?;
+    out.auto_pager(&config, "diff", true)?;
+    let diffcolors = DiffColors::new(out, &config)?;
 
-    let working_tree = try!(repo.find_tree(try!(internals.working.write())));
-    let staged_tree = try!(repo.find_tree(try!(internals.staged.write())));
+    let working_tree = repo.find_tree(internals.working.write()?)?;
+    let staged_tree = repo.find_tree(internals.staged.write()?)?;
 
     write_series_diff(out, repo, &diffcolors, Some(&staged_tree), Some(&working_tree))
 }
@@ -620,8 +620,8 @@ fn cmd_maybe_shell<S: AsRef<OsStr>>(program: S, args: bool) -> Command {
 }
 
 fn run_editor<S: AsRef<OsStr>>(config: &Config, filename: S) -> Result<()> {
-    let editor = try!(get_editor(&config));
-    let editor_status = try!(cmd_maybe_shell(editor, true).arg(&filename).status());
+    let editor = get_editor(&config)?;
+    let editor_status = cmd_maybe_shell(editor, true).arg(&filename).status()?;
     if !editor_status.success() {
         return Err(format!("Editor exited with status {}", editor_status).into());
     }
@@ -648,7 +648,7 @@ impl Output {
             if env::var_os("LV").is_none() {
                 cmd.env("LV", "-c");
             }
-            let child = try!(cmd.spawn());
+            let child = cmd.spawn()?;
             self.pager = Some(child);
             self.include_stderr = atty::is(atty::Stream::Stderr);
         }
@@ -665,13 +665,13 @@ impl Output {
         if !cfg!(unix) {
             return Ok(Style::new());
         }
-        let color_ui = try!(notfound_to_none(config.get_str("color.ui"))).unwrap_or("auto");
-        let color_cmd = try!(notfound_to_none(config.get_str(&format!("color.{}", command)))).unwrap_or(color_ui);
+        let color_ui = notfound_to_none(config.get_str("color.ui"))?.unwrap_or("auto");
+        let color_cmd = notfound_to_none(config.get_str(&format!("color.{}", command)))?.unwrap_or(color_ui);
         if color_cmd == "never" || Config::parse_bool(color_cmd) == Ok(false) {
             return Ok(Style::new());
         }
         if self.pager.is_some() {
-            let color_pager = try!(notfound_to_none(config.get_bool(&format!("color.pager")))).unwrap_or(true);
+            let color_pager = notfound_to_none(config.get_bool(&format!("color.pager")))?.unwrap_or(true);
             if !color_pager {
                 return Ok(Style::new());
             }
@@ -679,7 +679,7 @@ impl Output {
             return Ok(Style::new());
         }
         let cfg = format!("color.{}.{}", command, slot);
-        let color = try!(notfound_to_none(config.get_str(&cfg))).unwrap_or(default);
+        let color = notfound_to_none(config.get_str(&cfg))?.unwrap_or(default);
         colorparse::parse(color).map_err(|e| format!("Error parsing {}: {}", cfg, e).into())
    }
 
@@ -725,26 +725,26 @@ fn get_signature(config: &Config, which: &str) -> Result<git2::Signature<'static
     let name_var = ["GIT_", which, "_NAME"].concat();
     let email_var = ["GIT_", which, "_EMAIL"].concat();
     let which_lc = which.to_lowercase();
-    let name = try!(env::var(&name_var).or_else(
+    let name = env::var(&name_var).or_else(
             |_| config.get_string("user.name").or_else(
-                |_| Err(format!("Could not determine {} name: checked ${} and user.name in git config", which_lc, name_var)))));
-    let email = try!(env::var(&email_var).or_else(
+                |_| Err(format!("Could not determine {} name: checked ${} and user.name in git config", which_lc, name_var))))?;
+    let email = env::var(&email_var).or_else(
             |_| config.get_string("user.email").or_else(
                 |_| env::var("EMAIL").or_else(
-                    |_| Err(format!("Could not determine {} email: checked ${}, user.email in git config, and $EMAIL", which_lc, email_var))))));
-    Ok(try!(git2::Signature::now(&name, &email)))
+                    |_| Err(format!("Could not determine {} email: checked ${}, user.email in git config, and $EMAIL", which_lc, email_var)))))?;
+    Ok(git2::Signature::now(&name, &email)?)
 }
 
 fn commit_status(out: &mut Output, repo: &Repository, m: &ArgMatches, do_status: bool) -> Result<()> {
-    let config = try!(try!(repo.config()).snapshot());
+    let config = repo.config()?.snapshot()?;
     let shead = match repo.find_reference(SHEAD_REF) {
         Err(ref e) if e.code() == git2::ErrorCode::NotFound => { println!("No series; use \"git series start <name>\" to start"); return Ok(()); }
-        result => try!(result),
+        result => result?,
     };
-    let series_name = try!(shead_series_name(&shead));
+    let series_name = shead_series_name(&shead)?;
 
     if do_status {
-        try!(out.auto_pager(&config, "status", false));
+        out.auto_pager(&config, "status", false)?;
     }
     let get_color = |out: &Output, color: &str, default: &str| {
         if do_status {
@@ -754,14 +754,14 @@ fn commit_status(out: &mut Output, repo: &Repository, m: &ArgMatches, do_status:
         }
     };
     let color_normal = Style::new();
-    let color_header = try!(get_color(out, "header", "normal"));
-    let color_updated = try!(get_color(out, "updated", "green"));
-    let color_changed = try!(get_color(out, "changed", "red"));
+    let color_header = get_color(out, "header", "normal")?;
+    let color_updated = get_color(out, "updated", "green")?;
+    let color_changed = get_color(out, "changed", "red")?;
 
     let write_status = |status: &mut Vec<ansi_term::ANSIString>, diff: &Diff, heading: &str, color: &Style, show_hints: bool, hints: &[&str]| -> Result<bool> {
         let mut changes = false;
 
-        try!(diff.foreach(&mut |delta, _| {
+        diff.foreach(&mut |delta, _| {
             if !changes {
                 changes = true;
                 status.push(color_header.paint(format!("{}\n", heading.to_string())));
@@ -775,7 +775,7 @@ fn commit_status(out: &mut Output, repo: &Repository, m: &ArgMatches, do_status:
             status.push(color_normal.paint("        "));
             status.push(color.paint(format!("{:?}:   {}\n", delta.status(), delta.old_file().path().unwrap().to_str().unwrap())));
             true
-        }, None, None, None));
+        }, None, None, None)?;
 
         if changes {
             status.push(color_normal.paint("\n"));
@@ -787,43 +787,43 @@ fn commit_status(out: &mut Output, repo: &Repository, m: &ArgMatches, do_status:
     let mut status = Vec::new();
     status.push(color_header.paint(format!("On series {}\n", series_name)));
 
-    let mut internals = try!(Internals::read(repo));
-    let working_tree = try!(repo.find_tree(try!(internals.working.write())));
-    let staged_tree = try!(repo.find_tree(try!(internals.staged.write())));
+    let mut internals = Internals::read(repo)?;
+    let working_tree = repo.find_tree(internals.working.write()?)?;
+    let staged_tree = repo.find_tree(internals.staged.write()?)?;
 
     let shead_commit = match shead.resolve() {
-        Ok(r) => Some(try!(r.peel_to_commit())),
+        Ok(r) => Some(r.peel_to_commit()?),
         Err(ref e) if e.code() == git2::ErrorCode::NotFound => {
             status.push(color_header.paint("\nInitial series commit\n"));
             None
         }
-        Err(e) => try!(Err(e)),
+        Err(e) => Err(e)?,
     };
     let shead_tree = match shead_commit {
-        Some(ref c) => Some(try!(c.tree())),
+        Some(ref c) => Some(c.tree()?),
         None => None,
     };
 
     let commit_all = m.is_present("all");
 
     let (changes, tree) = if commit_all {
-        let diff = try!(repo.diff_tree_to_tree(shead_tree.as_ref(), Some(&working_tree), None));
-        let changes = try!(write_status(&mut status, &diff, "Changes to be committed:", &color_normal, false, &[]));
+        let diff = repo.diff_tree_to_tree(shead_tree.as_ref(), Some(&working_tree), None)?;
+        let changes = write_status(&mut status, &diff, "Changes to be committed:", &color_normal, false, &[])?;
         if !changes {
             status.push(color_normal.paint("nothing to commit; series unchanged\n"));
         }
         (changes, working_tree)
     } else {
-        let diff = try!(repo.diff_tree_to_tree(shead_tree.as_ref(), Some(&staged_tree), None));
-        let changes_to_be_committed = try!(write_status(&mut status, &diff,
+        let diff = repo.diff_tree_to_tree(shead_tree.as_ref(), Some(&staged_tree), None)?;
+        let changes_to_be_committed = write_status(&mut status, &diff,
                 "Changes to be committed:", &color_updated, do_status,
                 &["use \"git series commit\" to commit",
-                  "use \"git series unadd <file>...\" to undo add"]));
+                  "use \"git series unadd <file>...\" to undo add"])?;
 
-        let diff_not_staged = try!(repo.diff_tree_to_tree(Some(&staged_tree), Some(&working_tree), None));
-        let changes_not_staged = try!(write_status(&mut status, &diff_not_staged,
+        let diff_not_staged = repo.diff_tree_to_tree(Some(&staged_tree), Some(&working_tree), None)?;
+        let changes_not_staged = write_status(&mut status, &diff_not_staged,
                 "Changes not staged for commit:", &color_changed, do_status,
-                &["use \"git series add <file>...\" to update what will be committed"]));
+                &["use \"git series add <file>...\" to update what will be committed"])?;
 
         if !changes_to_be_committed {
             if changes_not_staged {
@@ -839,7 +839,7 @@ fn commit_status(out: &mut Output, repo: &Repository, m: &ArgMatches, do_status:
     let status = ansi_term::ANSIStrings(&status).to_string();
     if do_status || !changes {
         if do_status {
-            try!(write!(out, "{}", status));
+            write!(out, "{}", status)?;
         } else {
             return Err(status.into());
         }
@@ -855,9 +855,9 @@ fn commit_status(out: &mut Output, repo: &Repository, m: &ArgMatches, do_status:
 
     // Check that the base is still an ancestor of the series
     if let Some(base) = tree.get_name("base") {
-        if base.id() != series_id && !try!(repo.graph_descendant_of(series_id, base.id())) {
-            let (base_short_id, base_summary) = try!(commit_summarize_components(&repo, base.id()));
-            let (series_short_id, series_summary) = try!(commit_summarize_components(&repo, series_id));
+        if base.id() != series_id && !repo.graph_descendant_of(series_id, base.id())? {
+            let (base_short_id, base_summary) = commit_summarize_components(&repo, base.id())?;
+            let (series_short_id, series_summary) = commit_summarize_components(&repo, series_id)?;
             return Err(format!(concat!(
                        "Cannot commit: base {} is not an ancestor of patch series {}\n",
                        "base   {} {}\n",
@@ -872,36 +872,36 @@ fn commit_status(out: &mut Output, repo: &Repository, m: &ArgMatches, do_status:
         Some(s) => s.to_string(),
         None => {
             let filename = repo.path().join("SCOMMIT_EDITMSG");
-            let mut file = try!(File::create(&filename));
-            try!(write!(file, "{}", COMMIT_MESSAGE_COMMENT));
+            let mut file = File::create(&filename)?;
+            write!(file, "{}", COMMIT_MESSAGE_COMMENT)?;
             for line in status.lines() {
                 if line.is_empty() {
-                    try!(writeln!(file, "#"));
+                    writeln!(file, "#")?;
                 } else {
-                    try!(writeln!(file, "# {}", line));
+                    writeln!(file, "# {}", line)?;
                 }
             }
             if m.is_present("verbose") {
-                try!(writeln!(file, "{}\n{}", SCISSOR_LINE, SCISSOR_COMMENT));
-                try!(write_series_diff(&mut file, repo, &DiffColors::plain(), shead_tree.as_ref(), Some(&tree)));
+                writeln!(file, "{}\n{}", SCISSOR_LINE, SCISSOR_COMMENT)?;
+                write_series_diff(&mut file, repo, &DiffColors::plain(), shead_tree.as_ref(), Some(&tree))?;
             }
             drop(file);
-            try!(run_editor(&config, &filename));
-            let mut file = try!(File::open(&filename));
+            run_editor(&config, &filename)?;
+            let mut file = File::open(&filename)?;
             let mut msg = String::new();
-            try!(file.read_to_string(&mut msg));
+            file.read_to_string(&mut msg)?;
             if let Some(scissor_index) = msg.find(SCISSOR_LINE) {
                 msg.truncate(scissor_index);
             }
-            try!(git2::message_prettify(msg, git2::DEFAULT_COMMENT_CHAR))
+            git2::message_prettify(msg, git2::DEFAULT_COMMENT_CHAR)?
         }
     };
     if msg.is_empty() {
         return Err("Aborting series commit due to empty commit message.".into());
     }
 
-    let author = try!(get_signature(&config, "AUTHOR"));
-    let committer = try!(get_signature(&config, "COMMITTER"));
+    let author = get_signature(&config, "AUTHOR")?;
+    let committer = get_signature(&config, "COMMITTER")?;
     let mut parents: Vec<Oid> = Vec::new();
     // Include all commits from tree, to keep them reachable and fetchable.
     for e in tree.iter() {
@@ -909,63 +909,63 @@ fn commit_status(out: &mut Output, repo: &Repository, m: &ArgMatches, do_status:
             parents.push(e.id())
         }
     }
-    let parents = try!(parents_from_ids(repo, parents));
+    let parents = parents_from_ids(repo, parents)?;
     let parents_ref: Vec<&_> = shead_commit.iter().chain(parents.iter()).collect();
-    let new_commit_oid = try!(repo.commit(Some(SHEAD_REF), &author, &committer, &msg, &tree, &parents_ref));
+    let new_commit_oid = repo.commit(Some(SHEAD_REF), &author, &committer, &msg, &tree, &parents_ref)?;
 
     if commit_all {
-        internals.staged = try!(repo.treebuilder(Some(&tree)));
-        try!(internals.write(repo));
+        internals.staged = repo.treebuilder(Some(&tree))?;
+        internals.write(repo)?;
     }
 
-    let (new_commit_short_id, new_commit_summary) = try!(commit_summarize_components(&repo, new_commit_oid));
-    try!(writeln!(out, "[{} {}] {}", series_name, new_commit_short_id, new_commit_summary));
+    let (new_commit_short_id, new_commit_summary) = commit_summarize_components(&repo, new_commit_oid)?;
+    writeln!(out, "[{} {}] {}", series_name, new_commit_short_id, new_commit_summary)?;
 
     Ok(())
 }
 
 fn cover(repo: &Repository, m: &ArgMatches) -> Result<()> {
-    let mut internals = try!(Internals::read(repo));
+    let mut internals = Internals::read(repo)?;
 
-    let (working_cover_id, working_cover_content) = match try!(internals.working.get("cover")) {
+    let (working_cover_id, working_cover_content) = match internals.working.get("cover")? {
         None => (Oid::zero(), String::new()),
-        Some(entry) => (entry.id(), try!(std::str::from_utf8(try!(repo.find_blob(entry.id())).content())).to_string()),
+        Some(entry) => (entry.id(), std::str::from_utf8(repo.find_blob(entry.id())?.content())?.to_string()),
     };
 
     if m.is_present("delete") {
         if working_cover_id.is_zero() {
             return Err("No cover to delete".into());
         }
-        try!(internals.working.remove("cover"));
-        try!(internals.write(repo));
+        internals.working.remove("cover")?;
+        internals.write(repo)?;
         println!("Deleted cover letter");
         return Ok(());
     }
 
     let filename = repo.path().join("COVER_EDITMSG");
-    let mut file = try!(File::create(&filename));
+    let mut file = File::create(&filename)?;
     if working_cover_content.is_empty() {
-        try!(write!(file, "{}", COVER_LETTER_COMMENT));
+        write!(file, "{}", COVER_LETTER_COMMENT)?;
     } else {
-        try!(write!(file, "{}", working_cover_content));
+        write!(file, "{}", working_cover_content)?;
     }
     drop(file);
-    let config = try!(repo.config());
-    try!(run_editor(&config, &filename));
-    let mut file = try!(File::open(&filename));
+    let config = repo.config()?;
+    run_editor(&config, &filename)?;
+    let mut file = File::open(&filename)?;
     let mut msg = String::new();
-    try!(file.read_to_string(&mut msg));
-    let msg = try!(git2::message_prettify(msg, git2::DEFAULT_COMMENT_CHAR));
+    file.read_to_string(&mut msg)?;
+    let msg = git2::message_prettify(msg, git2::DEFAULT_COMMENT_CHAR)?;
     if msg.is_empty() {
         return Err("Empty cover letter; not changing.\n(To delete the cover letter, use \"git series cover -d\".)".into());
     }
 
-    let new_cover_id = try!(repo.blob(msg.as_bytes()));
+    let new_cover_id = repo.blob(msg.as_bytes())?;
     if new_cover_id == working_cover_id {
         println!("Cover letter unchanged");
     } else {
-        try!(internals.working.insert("cover", new_cover_id, GIT_FILEMODE_BLOB as i32));
-        try!(internals.write(repo));
+        internals.working.insert("cover", new_cover_id, GIT_FILEMODE_BLOB as i32)?;
+        internals.write(repo)?;
         println!("Updated cover letter");
     }
 
@@ -973,8 +973,8 @@ fn cover(repo: &Repository, m: &ArgMatches) -> Result<()> {
 }
 
 fn cp_mv(repo: &Repository, m: &ArgMatches, mv: bool) -> Result<()> {
-    let shead_target = if let Some(shead) = try!(notfound_to_none(repo.find_reference(SHEAD_REF))) {
-        Some(try!(shead_series_name(&shead)))
+    let shead_target = if let Some(shead) = notfound_to_none(repo.find_reference(SHEAD_REF))? {
+        Some(shead_series_name(&shead)?)
     } else {
         None
     };
@@ -982,22 +982,22 @@ fn cp_mv(repo: &Repository, m: &ArgMatches, mv: bool) -> Result<()> {
     let dest = source_dest.next_back().unwrap();
     let (update_shead, source) = match source_dest.next_back().map(String::from) {
         Some(name) => (shead_target.as_ref() == Some(&name), name),
-        None => (true, try!(shead_target.ok_or("No current series"))),
+        None => (true, shead_target.ok_or("No current series")?),
     };
 
-    if try!(Internals::exists(&repo, dest)) {
+    if Internals::exists(&repo, dest)? {
         return Err(format!("The destination series \"{}\" already exists", dest).into());
     }
-    if !try!(Internals::copy(&repo, &source, &dest)) {
+    if !Internals::copy(&repo, &source, &dest)? {
         return Err(format!("The source series \"{}\" does not exist", source).into());
     }
 
     if mv {
         if update_shead {
             let prefixed_dest = &[SERIES_PREFIX, dest].concat();
-            try!(repo.reference_symbolic(SHEAD_REF, &prefixed_dest, true, &format!("git series mv {} {}", source, dest)));
+            repo.reference_symbolic(SHEAD_REF, &prefixed_dest, true, &format!("git series mv {} {}", source, dest))?;
         }
-        try!(Internals::delete(&repo, &source));
+        Internals::delete(&repo, &source)?;
     }
 
     Ok(())
@@ -1119,14 +1119,14 @@ impl DiffColors {
     }
 
     fn new(out: &Output, config: &Config) -> Result<Self> {
-        let old = try!(out.get_color(&config, "diff", "old", "red"));
-        let new = try!(out.get_color(&config, "diff", "new", "green"));
+        let old = out.get_color(&config, "diff", "old", "red")?;
+        let new = out.get_color(&config, "diff", "new", "green")?;
         Ok(DiffColors {
-            commit: try!(out.get_color(&config, "diff", "commit", "yellow")),
-            meta: try!(out.get_color(&config, "diff", "meta", "bold")),
-            frag: try!(out.get_color(&config, "diff", "frag", "cyan")),
-            func: try!(out.get_color(&config, "diff", "func", "normal")),
-            context: try!(out.get_color(&config, "diff", "context", "normal")),
+            commit: out.get_color(&config, "diff", "commit", "yellow")?,
+            meta: out.get_color(&config, "diff", "meta", "bold")?,
+            frag: out.get_color(&config, "diff", "frag", "cyan")?,
+            func: out.get_color(&config, "diff", "func", "normal")?,
+            context: out.get_color(&config, "diff", "context", "normal")?,
             old: old,
             new: new,
             series_old: old.reverse(),
@@ -1136,8 +1136,8 @@ impl DiffColors {
 }
 
 fn diffstat(diff: &Diff) -> Result<String> {
-    let stats = try!(diff.stats());
-    let stats_buf = try!(stats.to_buf(git2::DiffStatsFormat::FULL|git2::DiffStatsFormat::INCLUDE_SUMMARY, 72));
+    let stats = diff.stats()?;
+    let stats_buf = stats.to_buf(git2::DiffStatsFormat::FULL|git2::DiffStatsFormat::INCLUDE_SUMMARY, 72)?;
     Ok(stats_buf.as_str().unwrap().to_string())
 }
 
@@ -1145,7 +1145,7 @@ fn write_diff<W: IoWrite>(f: &mut W, colors: &DiffColors, diff: &Diff, simplify:
     let mut err = Ok(());
     let mut lines = 0;
     let normal = Style::new();
-    try!(diff.print(git2::DiffFormat::Patch, |_, _, l| {
+    diff.print(git2::DiffFormat::Patch, |_, _, l| {
         err = || -> Result<()> {
             let o = l.origin();
             let style = match o {
@@ -1204,33 +1204,33 @@ fn write_diff<W: IoWrite>(f: &mut W, colors: &DiffColors, diff: &Diff, simplify:
                     }
                 }
             }
-            try!(ansi_term::ANSIByteStrings(&v).write_to(f));
+            ansi_term::ANSIByteStrings(&v).write_to(f)?;
             Ok(())
         }();
         err.is_ok()
-    }));
-    try!(err);
+    })?;
+    err?;
     Ok(lines)
 }
 
 fn get_commits(repo: &Repository, base: Oid, series: Oid) -> Result<Vec<Commit>> {
-    let mut revwalk = try!(repo.revwalk());
+    let mut revwalk = repo.revwalk()?;
     revwalk.set_sorting(git2::Sort::TOPOLOGICAL|git2::Sort::REVERSE);
-    try!(revwalk.push(series));
-    try!(revwalk.hide(base));
+    revwalk.push(series)?;
+    revwalk.hide(base)?;
     revwalk.map(|c| {
-        let id = try!(c);
-        let commit = try!(repo.find_commit(id));
+        let id = c?;
+        let commit = repo.find_commit(id)?;
         Ok(commit)
     }).collect()
 }
 
 fn write_commit_range_diff<W: IoWrite>(out: &mut W, repo: &Repository, colors: &DiffColors, (base1, series1): (Oid, Oid), (base2, series2): (Oid, Oid)) -> Result<()> {
-    let mut commits1 = try!(get_commits(repo, base1, series1));
-    let mut commits2 = try!(get_commits(repo, base2, series2));
+    let mut commits1 = get_commits(repo, base1, series1)?;
+    let mut commits2 = get_commits(repo, base2, series2)?;
     for commit in commits1.iter().chain(commits2.iter()) {
         if commit.parent_ids().count() > 1 {
-            try!(writeln!(out, "(Diffs of series with merge commits ({}) not yet supported)", commit.id()));
+            writeln!(out, "(Diffs of series with merge commits ({}) not yet supported)", commit.id())?;
             return Ok(());
         }
     }
@@ -1244,28 +1244,28 @@ fn write_commit_range_diff<W: IoWrite>(out: &mut W, repo: &Repository, colors: &
         return Ok(());
     }
     let commit_text = &|commit: &Commit| {
-        let parent = try!(commit.parent(0));
+        let parent = commit.parent(0)?;
         let author = commit.author();
-        let diff = try!(repo.diff_tree_to_tree(Some(&parent.tree().unwrap()), Some(&commit.tree().unwrap()), None));
+        let diff = repo.diff_tree_to_tree(Some(&parent.tree().unwrap()), Some(&commit.tree().unwrap()), None)?;
         let mut v = Vec::new();
-        try!(v.write_all(b"From: "));
-        try!(v.write_all(author.name_bytes()));
-        try!(v.write_all(b" <"));
-        try!(v.write_all(author.email_bytes()));
-        try!(v.write_all(b">\n\n"));
-        try!(v.write_all(commit.message_bytes()));
-        try!(v.write_all(b"\n"));
-        let lines = try!(write_diff(&mut v, colors, &diff, true));
+        v.write_all(b"From: ")?;
+        v.write_all(author.name_bytes())?;
+        v.write_all(b" <")?;
+        v.write_all(author.email_bytes())?;
+        v.write_all(b">\n\n")?;
+        v.write_all(commit.message_bytes())?;
+        v.write_all(b"\n")?;
+        let lines = write_diff(&mut v, colors, &diff, true)?;
         Ok((v, lines))
     };
-    let texts1: Vec<_> = try!(commits1.iter().map(commit_text).collect::<Result<_>>());
-    let texts2: Vec<_> = try!(commits2.iter().map(commit_text).collect::<Result<_>>());
+    let texts1: Vec<_> = commits1.iter().map(commit_text).collect::<Result<_>>()?;
+    let texts2: Vec<_> = commits2.iter().map(commit_text).collect::<Result<_>>()?;
 
     let mut weights = Vec::with_capacity(n*n);
     for i1 in 0..ncommits1 {
         for i2 in 0..ncommits2 {
-            let patch = try!(git2::Patch::from_buffers(&texts1[i1].0, None, &texts2[i2].0, None, None));
-            let (_, additions, deletions) = try!(patch.line_stats());
+            let patch = git2::Patch::from_buffers(&texts1[i1].0, None, &texts2[i2].0, None, None)?;
+            let (_, additions, deletions) = patch.line_stats()?;
             weights.push(additions+deletions);
         }
         let w = texts1[i1].1 / 2;
@@ -1282,7 +1282,7 @@ fn write_commit_range_diff<W: IoWrite>(out: &mut W, repo: &Repository, colors: &
         }
     }
     let mut weight_matrix = munkres::WeightMatrix::from_row_vec(n, weights);
-    let result = try!(munkres::solve_assignment(&mut weight_matrix));
+    let result = munkres::solve_assignment(&mut weight_matrix)?;
 
     #[derive(Copy, Clone, Debug, PartialEq, Eq)]
     enum CommitState { Unhandled, Handled, Deleted };
@@ -1334,8 +1334,8 @@ fn write_commit_range_diff<W: IoWrite>(out: &mut W, repo: &Repository, colors: &
 
     let offset = ncommon + 1;
     let nwidth = max(ncommits1 + offset, ncommits2 + offset).to_string().len();
-    let commits1_summaries: Vec<_> = try!(commits1.iter_mut().map(commit_obj_summarize_components).collect());
-    let commits2_summaries: Vec<_> = try!(commits2.iter_mut().map(commit_obj_summarize_components).collect());
+    let commits1_summaries: Vec<_> = commits1.iter_mut().map(commit_obj_summarize_components).collect::<Result<_>>()?;
+    let commits2_summaries: Vec<_> = commits2.iter_mut().map(commit_obj_summarize_components).collect::<Result<_>>()?;
     let idwidth = commits1_summaries.iter().chain(commits2_summaries.iter()).map(|&(ref short_id, _)| short_id.len()).max().unwrap();
     for commit_pair in commit_pairs {
         match commit_pair {
@@ -1353,7 +1353,7 @@ fn write_commit_range_diff<W: IoWrite>(out: &mut W, repo: &Repository, colors: &
                 nl(&mut v);
             }
             (Some(i1), Some(i2)) => {
-                let mut patch = try!(git2::Patch::from_buffers(&texts1[i1].0, None, &texts2[i2].0, None, None));
+                let mut patch = git2::Patch::from_buffers(&texts1[i1].0, None, &texts2[i2].0, None, None)?;
                 let (old, ch, new) = if let Delta::Unmodified = patch.delta().status() {
                     (colors.commit, '=', colors.commit)
                 } else {
@@ -1366,7 +1366,7 @@ fn write_commit_range_diff<W: IoWrite>(out: &mut W, repo: &Repository, colors: &
                 v.push(new.paint(format!("{:nwidth$}: {:idwidth$}", i2 + offset, c2_short_id, nwidth=nwidth, idwidth=idwidth).as_bytes().to_owned()));
                 v.push(colors.commit.paint(format!(" {}", c2_summary).as_bytes().to_owned()));
                 nl(&mut v);
-                try!(patch.print(&mut |_, _, l| {
+                patch.print(&mut |_, _, l| {
                     let o = l.origin();
                     let style = match o {
                         '-'|'<' => old,