diff options
author | Teddy Wing | 2021-06-13 12:58:33 +0200 |
---|---|---|
committer | Teddy Wing | 2021-06-13 12:58:33 +0200 |
commit | fa002d88284fd1622f68229c47eba7c688c81ed9 (patch) | |
tree | 82801f1e50d0a9ee08b2c696fbfedb3a9cd8cfac /src | |
parent | ec68bbe068ce58f970b154421d8250ad982ee91e (diff) | |
download | reflectub-fa002d88284fd1622f68229c47eba7c688c81ed9.tar.bz2 |
run(): Return multiple errors
Return all errors from repo processing. This allows us to provide
information on all errors that happened while processing, but continue
processing all the repos even if there's an error in one of them.
A new `MultiError` type wraps a list of errors to do this.
Diffstat (limited to 'src')
-rw-r--r-- | src/main.rs | 63 |
1 files changed, 51 insertions, 12 deletions
diff --git a/src/main.rs b/src/main.rs index 15f0898..ce5d370 100644 --- a/src/main.rs +++ b/src/main.rs @@ -28,6 +28,7 @@ use rusqlite; use reflectub::{database, git, github}; use std::env; +use std::fmt; use std::fs; use std::io; use std::path::{Path, PathBuf}; @@ -39,19 +40,47 @@ fn main() { match run() { Ok(_) => (), Err(e) => { - eprint!("error"); - - for cause in e.chain() { - eprint!(": {}", cause); - } - - eprintln!(); + eprintln!("error: {}", e); process::exit(exitcode::SOFTWARE); }, }; } + +#[derive(Debug, thiserror::Error)] +struct MultiError { + errors: Vec<anyhow::Error>, + // errors: Vec<Box<dyn std::error::Error>>, +} + +impl fmt::Display for MultiError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "{}", + self.errors + .iter() + .map(|e| format!("{:#}", e)) + .collect::<Vec<_>>() + .join("\n"), + ) + } +} + +impl From<anyhow::Error> for MultiError { + fn from(error: anyhow::Error) -> Self { + MultiError { errors: vec![error] } + } +} + +impl From<Vec<anyhow::Error>> for MultiError { + fn from(errors: Vec<anyhow::Error>) -> Self { + MultiError { errors: errors } + } +} + + fn print_usage(opts: &Options) { print!( "{}", @@ -59,7 +88,7 @@ fn print_usage(opts: &Options) { ); } -fn run() -> anyhow::Result<()> { +fn run() -> Result<(), MultiError> { let args: Vec<String> = env::args().collect(); let mut opts = Options::new(); @@ -70,7 +99,8 @@ fn run() -> anyhow::Result<()> { opts.optflag("h", "help", "print this help menu"); opts.optflag("V", "version", "show the program version"); - let opt_matches = opts.parse(&args[1..])?; + let opt_matches = opts.parse(&args[1..]) + .map_err(anyhow::Error::new)?; if opt_matches.opt_present("h") { print_usage(&opts); @@ -110,7 +140,8 @@ fn run() -> anyhow::Result<()> { let base_cgitrc = opt_matches.opt_str("cgitrc") .map(|s| PathBuf::from(s)); - let repos = github::fetch_repos(username)?; + let repos = github::fetch_repos(username) + .map_err(anyhow::Error::new)?; let db = database::Db::connect(&database_file) .context("unable to connect to database")?; @@ -118,7 +149,7 @@ fn run() -> anyhow::Result<()> { db.create() .context("unable to create database")?; - let _results: anyhow::Result<()> = repos[..2].par_iter() + let errors: Vec<_> = repos[..2].par_iter() .map(|repo| { dbg!("Thread", std::thread::current().id()); @@ -130,8 +161,15 @@ fn run() -> anyhow::Result<()> { max_repo_size_bytes, ) }) + .filter(|r| r.is_err()) + + // `e` should always be an error. + .map(|e| e.err().unwrap()) .collect(); - // TODO: Return errors + + if errors.len() > 0 { + return Err(MultiError::from(errors)) + } Ok(()) } @@ -144,6 +182,7 @@ fn process_repo( base_cgitrc: Option<PathBuf>, max_repo_size_bytes: Option<u64>, ) -> anyhow::Result<()> { + anyhow::bail!("test"); if let Some(max_repo_size_bytes) = max_repo_size_bytes { if is_repo_oversize(repo.size, max_repo_size_bytes) { return Ok(()); |