Skip to content

Commit

Permalink
use error_chain for error handling
Browse files Browse the repository at this point in the history
  • Loading branch information
o2sh committed Oct 11, 2020
1 parent 24a3666 commit 444f3b2
Show file tree
Hide file tree
Showing 8 changed files with 52 additions and 81 deletions.
17 changes: 17 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ image = "0.23.10"
regex = "1"
futures = "0.3.6"
tokio = { version = "0.2.22", features = ["full"] }
error-chain = "0.12"

[target.'cfg(windows)'.dependencies]
ansi_term = "0.12"
Expand Down
48 changes: 12 additions & 36 deletions src/error.rs
Original file line number Diff line number Diff line change
@@ -1,39 +1,15 @@
/// Custom error type
#[derive(Debug)]
pub enum Error {
/// Sourcecode could be located
SourceCodeNotFound,
/// Git is not installed or did not function properly
GitNotInstalled,
/// Did not find any git data in the directory
NoGitData,
/// An IO error occoured while reading ./
ReadDirectory,
/// Not in a Git Repo
NotGitRepo,
/// Error while getting branch info
BareGitRepo,
/// Repository is a bare git repo
ReferenceInfoError,
/// Image probably doesn't exist or has wrong format
ImageLoadError,
/// Could not initialize the license detector
LicenseDetectorError,
}
use colored::Colorize;
use error_chain::error_chain;
use std::io::Write;

impl std::fmt::Display for Error {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
let content = match self {
Error::SourceCodeNotFound => "Could not find any source code in this directory",
Error::GitNotInstalled => "Git failed to execute",
Error::NoGitData => "Could not retrieve git configuration data",
Error::ReadDirectory => "Could not read directory",
Error::NotGitRepo => "Could not find a valid git repo on the current path",
Error::BareGitRepo => "Unable to run onefetch on bare git repos",
Error::ReferenceInfoError => "Error while retrieving reference information",
Error::ImageLoadError => "Could not load the specified image",
Error::LicenseDetectorError => "Could not initialize the license detector",
};
write!(f, "{}", content)
error_chain! {
foreign_links {
Clap(::clap::Error) #[cfg(feature = "application")];
Io(::std::io::Error);
ParseIntError(::std::num::ParseIntError);
}
}

pub fn default_error_handler(error: &Error, output: &mut dyn Write) {
writeln!(output, "{}: {}", "[onefetch error]".red(), error).ok();
}
14 changes: 0 additions & 14 deletions src/exit_codes.rs

This file was deleted.

19 changes: 9 additions & 10 deletions src/info.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
use {
crate::{
error::*,
language::Language,
license::Detector,
options::Options,
{AsciiArt, CommitInfo, Error},
{AsciiArt, CommitInfo},
},
colored::{Color, ColoredString, Colorize},
git2::Repository,
Expand All @@ -13,8 +14,6 @@ use {
tokio::process::Command,
};

type Result<T> = std::result::Result<T, crate::Error>;

const LICENSE_FILES: [&str; 3] = ["LICENSE", "LICENCE", "COPYING"];

#[derive(Default)]
Expand Down Expand Up @@ -377,8 +376,8 @@ impl std::fmt::Display for Info {
impl Info {
#[tokio::main]
pub async fn new(config: Options) -> Result<Info> {
let repo = Repository::discover(&config.path).map_err(|_| Error::NotGitRepo)?;
let workdir = repo.workdir().ok_or(Error::BareGitRepo)?;
let repo = Repository::discover(&config.path).chain_err(||"Could not find a valid git repo on the current path")?;
let workdir = repo.workdir().chain_err(||"Unable to run onefetch on bare git repo")?;
let workdir_str = workdir.to_str().unwrap();
let (languages_stats, number_of_lines) =
Language::get_language_stats(workdir_str, &config.excluded)?;
Expand Down Expand Up @@ -486,7 +485,7 @@ impl Info {
}

async fn get_repo_name_and_url(repo: &Repository) -> (String, String) {
let config = repo.config().map_err(|_| Error::NoGitData);
let config = repo.config().chain_err(|| "Could not retrieve git configuration data");
let mut remote_url = String::new();
let mut repository_name = String::new();

Expand Down Expand Up @@ -519,9 +518,9 @@ impl Info {
}

async fn get_current_commit_info(repo: &Repository) -> Result<CommitInfo> {
let head = repo.head().map_err(|_| Error::ReferenceInfoError)?;
let head_oid = head.target().ok_or(Error::ReferenceInfoError)?;
let refs = repo.references().map_err(|_| Error::ReferenceInfoError)?;
let head = repo.head().chain_err(|| "Error while retrieving reference information")?;
let head_oid = head.target().ok_or("Error while retrieving reference information")?;
let refs = repo.references().chain_err(|| "Error while retrieving reference information")?;
let refs_info = refs
.filter_map(|reference| match reference {
Ok(reference) => match (reference.target(), reference.shorthand()) {
Expand Down Expand Up @@ -754,7 +753,7 @@ impl Info {
let detector = Detector::new()?;

let mut output = fs::read_dir(dir)
.map_err(|_| Error::ReadDirectory)?
.chain_err(|| "Could not read directory")?
.filter_map(std::result::Result::ok)
.map(|entry| entry.path())
.filter(|entry| {
Expand Down
4 changes: 2 additions & 2 deletions src/language.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use {
crate::{Error, Result},
crate::error::*,
colored::Color,
regex::Regex,
std::collections::HashMap,
Expand Down Expand Up @@ -185,7 +185,7 @@ impl Language {
) -> Result<(Vec<(Language, f64)>, usize)> {
let tokei_langs = project_languages(&dir, ignored_directories);
let languages_stat =
Language::get_languages_stat(&tokei_langs).ok_or(Error::SourceCodeNotFound)?;
Language::get_languages_stat(&tokei_langs).ok_or("ErrorKind::SourceCodeNotFound()")?;
let mut stat_vec: Vec<(_, _)> = languages_stat.into_iter().collect();
stat_vec.sort_by(|a, b| a.1.partial_cmp(&b.1).unwrap().reverse());
let loc = get_total_loc(&tokei_langs);
Expand Down
6 changes: 2 additions & 4 deletions src/license.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
use askalono::{Store, TextData};

use crate::Error;

type Result<T> = std::result::Result<T, Error>;
use crate::error::*;

static CACHE_DATA: &[u8] = include_bytes!("../resources/licenses/cache.bin.zstd");
const MIN_THRESHOLD: f32 = 0.8;
Expand All @@ -15,7 +13,7 @@ impl Detector {
pub fn new() -> Result<Self> {
Store::from_cache(CACHE_DATA)
.map(|store| Self { store })
.map_err(|_| Error::LicenseDetectorError)
.map_err(|_| "Could not initialize the license detector".into())
}

pub fn analyze(&self, text: &str) -> Option<String> {
Expand Down
24 changes: 9 additions & 15 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,35 +1,33 @@
// `error_chain!` can recurse deeply
#![recursion_limit = "1024"]

use {
ascii_art::AsciiArt,
colored::Colorize,
commit_info::CommitInfo,
error::Error,
exit_codes::ExitCode,
error::*,
info::Info,
language::Language,
process::{Command, Stdio},
std::{convert::From, env, io::Write, process, result, str::FromStr},
std::{convert::From, env, process, str::FromStr},
strum::IntoEnumIterator,
};

mod ascii_art;
mod clap_app;
mod commit_info;
mod error;
mod exit_codes;
mod image_backends;
mod info;
mod language;
mod license;
mod options;

type Result<T> = result::Result<T, Error>;

fn run() -> Result<()> {
#[cfg(windows)]
let _ = ansi_term::enable_ansi_support();

if !is_git_installed() {
return Err(Error::GitNotInstalled);
return Err("Git failed to execute!".into());
}

let matches = clap_app::build_app().get_matches_from(env::args_os());
Expand All @@ -45,7 +43,7 @@ fn run() -> Result<()> {
};

let image = if let Some(image_path) = matches.value_of("image") {
Some(image::open(image_path).map_err(|_| Error::ImageLoadError)?)
Some(image::open(image_path).chain_err(|| "Could not load the specified image")?)
} else {
None
};
Expand Down Expand Up @@ -110,20 +108,16 @@ fn main() {
let result = run();
match result {
Ok(_) => {
process::exit(ExitCode::Success.into());
process::exit(0);
}
Err(error) => {
let stderr = std::io::stderr();
default_error_handler(&error, &mut stderr.lock());
process::exit(ExitCode::GeneralError.into());
process::exit(1);
}
}
}

pub fn default_error_handler(error: &Error, output: &mut dyn Write) {
writeln!(output, "{}: {}", "[onefetch error]".red(), error).ok();
}

fn is_git_installed() -> bool {
Command::new("git")
.arg("--version")
Expand Down

0 comments on commit 444f3b2

Please sign in to comment.