summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSascha Grunert <mail@saschagrunert.de>2016-11-16 14:30:54 +0100
committerSascha Grunert <mail@saschagrunert.de>2016-11-16 14:30:54 +0100
commit0adc9580f67cfac66b5b1a66b643cb8fefa66a99 (patch)
treefe6d58fe5189081ad53856c7f1de3a7df36fd9aa
parent415071cb9c98084cb9aaa104e328e3994d614035 (diff)
Improved main error handling
-rw-r--r--.gitjournal.toml2
-rw-r--r--src/config.rs43
-rw-r--r--src/errors.rs127
-rw-r--r--src/lib.rs126
-rw-r--r--src/logger.rs18
-rw-r--r--src/main.rs59
-rw-r--r--src/parser.rs145
7 files changed, 250 insertions, 270 deletions
diff --git a/.gitjournal.toml b/.gitjournal.toml
index 0f34c51..508a97e 100644
--- a/.gitjournal.toml
+++ b/.gitjournal.toml
@@ -7,4 +7,4 @@ excluded_commit_tags = []
show_commit_hash = false
show_prefix = false
sort_by = "date"
-template_prefix = "JIRA-1234"
+template_prefix = ""
diff --git a/src/config.rs b/src/config.rs
index fd7b95b..da641de 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -3,45 +3,13 @@
//!
use rustc_serialize::Encodable;
-use toml::{Encoder, Value, Parser, encode_str, decode};
-use toml;
+use toml::{self, Encoder, Value, Parser, encode_str, decode};
-use std::io;
-use std::fmt;
use std::fs::File;
use std::path::PathBuf;
use std::io::prelude::*;
-/// An enumeration of possible errors that can happen when working with the configuration.
-#[derive(Debug)]
-pub enum Error {
- /// Erros related to the toml parsing.
- Toml(toml::Error),
-
- /// Erros related to the system IO, like saving the configuration file.
- Io(io::Error),
-}
-
-impl From<toml::Error> for Error {
- fn from(err: toml::Error) -> Error {
- Error::Toml(err)
- }
-}
-
-impl From<io::Error> for Error {
- fn from(err: io::Error) -> Error {
- Error::Io(err)
- }
-}
-
-impl fmt::Display for Error {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- match *self {
- Error::Toml(ref err) => write!(f, "Toml: {}", err),
- Error::Io(ref err) => write!(f, "Io: {}", err),
- }
- }
-}
+use errors::{GitJournalResult, internal_error};
/// The configuration structure for git-journal.
#[derive(Default, Debug, Clone, PartialEq, RustcEncodable, RustcDecodable)]
@@ -122,14 +90,13 @@ impl Config {
/// # Errors
/// When toml encoding or file creation failed.
///
- pub fn save_default_config(&self, path: &str) -> Result<String, Error> {
+ pub fn save_default_config(&self, path: &str) -> GitJournalResult<String> {
let mut encoder = Encoder::new();
self.encode(&mut encoder)?;
let toml_string = encode_str(&Value::Table(encoder.toml));
let path_buf = self.get_path_with_filename(path);
- let path_string = path_buf.to_str()
- .ok_or(io::Error::new(io::ErrorKind::Other, "Cannot convert path to string"))?;
+ let path_string = path_buf.to_str().ok_or(internal_error("IO", "Cannot convert path to string"))?;
let mut file = File::create(&path_buf)?;
file.write_all(toml_string.as_bytes())?;
@@ -148,7 +115,7 @@ impl Config {
/// # Errors
/// When toml decoding or file opening failed.
///
- pub fn load(&mut self, path: &str) -> Result<(), Error> {
+ pub fn load(&mut self, path: &str) -> GitJournalResult<()> {
let path_buf = self.get_path_with_filename(path);
let mut file = File::open(path_buf)?;
let mut toml_string = String::new();
diff --git a/src/errors.rs b/src/errors.rs
new file mode 100644
index 0000000..3074656
--- /dev/null
+++ b/src/errors.rs
@@ -0,0 +1,127 @@
+//! Basic error handling mechanisms
+
+use std::error::Error;
+use std::{fmt, io, num};
+
+use git2;
+use log;
+use term;
+use toml;
+
+/// The result type for GitJournal
+pub type GitJournalResult<T> = Result<T, Box<GitJournalError>>;
+
+/// GitJournal error trait
+pub trait GitJournalError: Error + Send + 'static {
+ /// The internal cause for the error
+ fn gitjournal_cause(&self) -> Option<&GitJournalError> {
+ None
+ }
+
+ /// Convert the `GitJournalError` to an `Error`
+ fn as_error(&self) -> &Error
+ where Self: Sized
+ {
+ self as &Error
+ }
+}
+
+impl Error for Box<GitJournalError> {
+ fn description(&self) -> &str {
+ (**self).description()
+ }
+ fn cause(&self) -> Option<&Error> {
+ (**self).cause()
+ }
+}
+
+impl GitJournalError for Box<GitJournalError> {
+ fn gitjournal_cause(&self) -> Option<&GitJournalError> {
+ (**self).gitjournal_cause()
+ }
+}
+
+/// Concrete errors
+struct ConcreteGitJournalError {
+ description: String,
+ detail: Option<String>,
+ cause: Option<Box<Error + Send>>,
+}
+
+impl fmt::Display for ConcreteGitJournalError {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "{}", self.description)?;
+ if let Some(ref s) = self.detail {
+ write!(f, " ({})", s)?;
+ }
+ Ok(())
+ }
+}
+
+impl fmt::Debug for ConcreteGitJournalError {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ fmt::Display::fmt(self, f)
+ }
+}
+
+impl Error for ConcreteGitJournalError {
+ fn description(&self) -> &str {
+ &self.description
+ }
+ fn cause(&self) -> Option<&Error> {
+ self.cause.as_ref().map(|c| {
+ let e: &Error = &**c;
+ e
+ })
+ }
+}
+
+impl GitJournalError for ConcreteGitJournalError {}
+
+/// Various error implementors
+macro_rules! from_error {
+ ($($p:ty,)*) => (
+ $(impl From<$p> for Box<GitJournalError> {
+ fn from(t: $p) -> Box<GitJournalError> { Box::new(t) }
+ })*
+ )
+}
+
+from_error! {
+ git2::Error,
+ io::Error,
+ log::ShutdownLoggerError,
+ num::ParseIntError,
+ term::Error,
+ toml::Error,
+}
+
+impl GitJournalError for git2::Error {}
+impl GitJournalError for io::Error {}
+impl GitJournalError for log::ShutdownLoggerError {}
+impl GitJournalError for num::ParseIntError {}
+impl GitJournalError for term::Error {}
+impl GitJournalError for toml::Error {}
+
+/// Raise and internal error
+pub fn internal_error(error: &str, detail: &str) -> Box<GitJournalError> {
+ Box::new(ConcreteGitJournalError {
+ description: error.to_string(),
+ detail: Some(detail.to_string()),
+ cause: None,
+ })
+}
+
+pub fn internal(error: &fmt::Display) -> Box<GitJournalError> {
+ Box::new(ConcreteGitJournalError {
+ description: error.to_string(),
+ detail: None,
+ cause: None,
+ })
+}
+
+macro_rules! bail {
+ ($($fmt:tt)*) => (
+ return Err(::errors::internal(&format_args!($($fmt)*)))
+ )
+}
diff --git a/src/lib.rs b/src/lib.rs
index 8784988..baab667 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -39,81 +39,29 @@ extern crate lazy_static;
#[macro_use]
extern crate log;
+use std::collections::BTreeMap;
+use std::fs::{File, OpenOptions};
+use std::io::prelude::*;
+use std::path::{Path, PathBuf};
+use std::{env, fs};
+
use chrono::{UTC, TimeZone};
use git2::{ObjectType, Oid, Repository};
use log::LogLevelFilter;
use rayon::prelude::*;
use toml::Value;
+pub use config::Config;
+pub use errors::{GitJournalResult, GitJournalError, internal_error};
use logger::Logger;
use parser::{Parser, ParsedTag, Tags};
-pub use config::Config;
-
-use std::{fmt, fs};
-use std::collections::BTreeMap;
-use std::fs::{File, OpenOptions};
-use std::path::{Path, PathBuf};
-use std::io::prelude::*;
+#[macro_use]
+mod errors;
mod logger;
mod parser;
pub mod config;
-/// An enumeration of possible errors that can happen when working with git-journal.
-#[derive(Debug)]
-pub enum Error {
- /// Erros related to the git repository.
- Git(git2::Error),
-
- /// Erros related to the system IO, like parsing of the configuration file.
- Io(std::io::Error),
-
- /// Errors related to the parsing and printing of the log.
- Parser(parser::Error),
-
- /// Errors related to the setup process.
- Setup(config::Error),
-
- /// Errors related to the commit message verification.
- Verify(String),
-}
-
-impl From<git2::Error> for Error {
- fn from(err: git2::Error) -> Error {
- Error::Git(err)
- }
-}
-
-impl From<std::io::Error> for Error {
- fn from(err: std::io::Error) -> Error {
- Error::Io(err)
- }
-}
-
-impl From<config::Error> for Error {
- fn from(err: config::Error) -> Error {
- Error::Setup(err)
- }
-}
-
-impl From<parser::Error> for Error {
- fn from(err: parser::Error) -> Error {
- Error::Parser(err)
- }
-}
-
-impl fmt::Display for Error {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- match *self {
- Error::Git(ref err) => write!(f, "Git: {}", err),
- Error::Io(ref err) => write!(f, "Io: {}", err),
- Error::Parser(ref err) => write!(f, "Parser: {}", err),
- Error::Setup(ref err) => write!(f, "Setup: {}", err),
- Error::Verify(ref err) => write!(f, "Verify: {}", err),
- }
- }
-}
-
/// The main structure of git-journal.
pub struct GitJournal {
/// The configuration structure
@@ -124,8 +72,8 @@ pub struct GitJournal {
}
impl GitJournal {
- /// Constructs a new `GitJournal<Result<GitJournal, Error>>`. Searches upwards if the given
- /// path does not contain the `.git` directory.
+ /// Constructs a new `GitJournal`. Searches upwards if the given path does not contain the
+ /// `.git` directory.
///
/// # Examples
///
@@ -139,12 +87,21 @@ impl GitJournal {
/// When not providing a path with a valid git repository ('.git' folder or the initial parsing
/// of the git tags failed.
///
- pub fn new(path: &str) -> Result<Self, Error> {
+ pub fn new(path: &str) -> GitJournalResult<Self> {
+ // Setup the logger if not already set
+ if log::set_logger(|max_log_level| {
+ max_log_level.set(LogLevelFilter::Info);
+ Box::new(Logger)
+ })
+ .is_err() {
+ warn!("Logger already set.");
+ };
+
// Search upwards for the .git directory
let mut path_buf = if path != "." {
PathBuf::from(path)
} else {
- std::env::current_dir()?
+ env::current_dir()?
};
'git_search: loop {
for dir in fs::read_dir(&path_buf)? {
@@ -184,15 +141,9 @@ impl GitJournal {
result: vec![],
};
- // Setup the logger if not already set
- if new_config.enable_debug {
- if log::set_logger(|max_log_level| {
- max_log_level.set(LogLevelFilter::Info);
- Box::new(Logger)
- })
- .is_err() {
- warn!("Logger already set.");
- };
+ // Shut down the logger if the user does not want debug output
+ if !new_config.enable_debug {
+ log::shutdown_logger()?;
}
// Return the git journal object
@@ -261,7 +212,7 @@ impl GitJournal {
/// - When the writing of the default configuration fails.
/// - When installation of the commit message (preparation) hook fails.
///
- pub fn setup(&self) -> Result<(), Error> {
+ pub fn setup(&self) -> GitJournalResult<()> {
// Save the default config
let output_file = Config::new().save_default_config(&self.path)?;
info!("Defaults written to '{}' file.", output_file);
@@ -275,11 +226,12 @@ impl GitJournal {
Ok(())
}
- fn install_git_hook(&self, name: &str, content: &str) -> Result<(), Error> {
+ fn install_git_hook(&self, name: &str, content: &str) -> GitJournalResult<()> {
let mut hook_path = PathBuf::from(&self.path);
hook_path.push(".git/hooks");
hook_path.push(name);
let mut hook_file: File;
+
if hook_path.exists() {
warn!("There is already a hook available in '{}'. Please verifiy \
the hook by hand after the installation.",
@@ -303,14 +255,14 @@ impl GitJournal {
}
#[cfg(unix)]
- fn chmod(&self, path: &Path, perms: u32) -> Result<(), Error> {
+ fn chmod(&self, path: &Path, perms: u32) -> GitJournalResult<()> {
use std::os::unix::prelude::PermissionsExt;
fs::set_permissions(path, fs::Permissions::from_mode(perms))?;
Ok(())
}
#[cfg(windows)]
- fn chmod(&self, _path: &Path, _perms: u32) -> Result<(), Error> {
+ fn chmod(&self, _path: &Path, _perms: u32) -> GitJournalResult<()> {
Ok(())
}
@@ -330,7 +282,7 @@ impl GitJournal {
/// # Errors
/// When the path is not available or writing the commit message fails.
///
- pub fn prepare(&self, path: &str, commit_type: Option<&str>) -> Result<(), Error> {
+ pub fn prepare(&self, path: &str, commit_type: Option<&str>) -> GitJournalResult<()> {
// If the message is not valid, assume a new commit and provide the template.
if let Err(error) = self.verify(path) {
// But if the message is provided via the cli with `-m`, then abort since
@@ -392,7 +344,7 @@ impl GitJournal {
/// # Errors
/// When the commit message is not valid due to RFC0001 or opening of the given file failed.
///
- pub fn verify(&self, path: &str) -> Result<(), Error> {
+ pub fn verify(&self, path: &str) -> GitJournalResult<()> {
// Open the file and read to string
let mut file = File::open(path)?;
let mut commit_message = String::new();
@@ -411,14 +363,14 @@ impl GitJournal {
file.read_to_string(&mut toml_string)?;
let toml = toml::Parser::new(&toml_string).parse()
- .ok_or(Error::Verify("Could not parse default toml template.".to_owned()))?;
+ .ok_or(internal_error("Verify", "Could not parse default toml template."))?;
let toml_tags = self.parser.get_tags_from_toml(&toml, vec![]);
let invalid_tags = tags.into_iter().filter(|tag| !toml_tags.contains(tag)).collect::<Vec<String>>();
if !invalid_tags.is_empty() {
warn!("These tags are not part of the default template: '{}'.",
invalid_tags.join(", "));
- return Err(Error::Verify("Not all tags exists in the default template.".to_owned()));
+ bail!("Not all tags exists in the default template.");
}
}
Ok(())
@@ -444,7 +396,7 @@ impl GitJournal {
max_tags_count: &u32,
all: &bool,
skip_unreleased: &bool)
- -> Result<(), Error> {
+ -> GitJournalResult<()> {
let repo = Repository::open(&self.path)?;
let mut revwalk = repo.revwalk()?;
@@ -533,7 +485,7 @@ impl GitJournal {
Ok(parsed_message) => {
*result = Some(parsed_message);
}
- Err(e) => warn!("Skipping commit: {}.", e),
+ Err(e) => warn!("Skipping commit: {}", e),
}
});
@@ -579,7 +531,7 @@ impl GitJournal {
/// # Errors
/// If the generation of the template was impossible.
///
- pub fn generate_template(&self) -> Result<(), Error> {
+ pub fn generate_template(&self) -> GitJournalResult<()> {
let mut tags = vec![parser::TOML_DEFAULT_KEY.to_owned()];
// Get all the tags
@@ -646,7 +598,7 @@ impl GitJournal {
/// # Errors
/// If some commit message could not be print.
///
- pub fn print_log(&self, compact: bool, template: Option<&str>, output: Option<&str>) -> Result<(), Error> {
+ pub fn print_log(&self, compact: bool, template: Option<&str>, output: Option<&str>) -> GitJournalResult<()> {
// Choose the template
let mut default_template = PathBuf::from(&self.path);
diff --git a/src/logger.rs b/src/logger.rs
index eed0a04..931e449 100644
--- a/src/logger.rs
+++ b/src/logger.rs
@@ -1,6 +1,10 @@
//! The logger implementation
use log::{Log, LogRecord, LogLevel, LogMetadata};
-use term;
+
+use term::stderr;
+use term::color::{BRIGHT_BLUE, GREEN, BRIGHT_YELLOW, RED};
+
+use errors::{GitJournalResult, internal_error};
/// The logging structure
pub struct Logger;
@@ -20,28 +24,28 @@ impl Log for Logger {
}
impl Logger {
- fn log_result(&self, record: &LogRecord) -> Result<(), term::Error> {
+ fn log_result(&self, record: &LogRecord) -> GitJournalResult<()> {
// We have to create a new terminal on each log because
// `term::Terminal<Output=std::io::Stderr> + Send + 'static` cannot be shared between
// threads safely'
- let mut t = term::stderr().ok_or(term::Error::NotSupported)?;
- t.fg(term::color::BRIGHT_BLUE)?;
+ let mut t = stderr().ok_or(internal_error("Term", "Could not create terminal"))?;
+ t.fg(BRIGHT_BLUE)?;
write!(t, "[git-journal] ")?;
match record.level() {
LogLevel::Info => {
- t.fg(term::color::GREEN)?;
+ t.fg(GREEN)?;
write!(t, "[OKAY] ")?;
t.reset()?;
writeln!(t, "{}", record.args())?;
}
LogLevel::Warn => {
- t.fg(term::color::BRIGHT_YELLOW)?;
+ t.fg(BRIGHT_YELLOW)?;
write!(t, "[WARN] ")?;
t.reset()?;
writeln!(t, "{}", record.args())?;
}
LogLevel::Error => {
- t.fg(term::color::RED)?;
+ t.fg(RED)?;
write!(t, "[ERROR] ")?;
t.reset()?;
writeln!(t, "{}", record.args())?;
diff --git a/src/main.rs b/src/main.rs
index 23e37df..ee8171c 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -7,44 +7,16 @@ extern crate clap;
extern crate log;
use std::process::exit;
-use std::{env, fmt, fs};
+use std::{env, fs};
use clap::{App, Shell};
-use gitjournal::GitJournal;
+use gitjournal::{GitJournal, GitJournalResult, GitJournalError, internal_error};
-fn error_and_exit(string: &str, error: Error) {
+fn error_and_exit(string: &str, error: Box<GitJournalError>) {
error!("{}: {}", string, error);
exit(1);
}
-enum Error {
- Cli,
- ParseInt(std::num::ParseIntError),
- GitJournal(gitjournal::Error),
-}
-
-impl From<gitjournal::Error> for Error {
- fn from(err: gitjournal::Error) -> Error {
- Error::GitJournal(err)
- }
-}
-
-impl From<std::num::ParseIntError> for Error {
- fn from(err: std::num::ParseIntError) -> Error {
- Error::ParseInt(err)
- }
-}
-
-impl fmt::Display for Error {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- match *self {
- Error::Cli => write!(f, "Cli argument parsing"),
- Error::ParseInt(ref err) => write!(f, "ParseInt: {}", err),
- Error::GitJournal(ref err) => write!(f, "GitJournal: {}", err),
- }
- }
-}
-
fn is_program_in_path(program: &str) -> bool {
if let Ok(path) = env::var("PATH") {
for p in path.split(':') {
@@ -63,12 +35,12 @@ fn main() {
}
}
-fn run() -> Result<(), Error> {
+fn run() -> GitJournalResult<()> {
// Load the CLI parameters from the yaml file
let yaml = load_yaml!("cli.yaml");
let mut app = App::from_yaml(yaml).version(crate_version!());
let matches = app.clone().get_matches();
- let path = matches.value_of("path").ok_or(Error::Cli)?;
+ let path = matches.value_of("path").ok_or(internal_error("Cli", "No 'path' provided"))?;
// Create the journal
let mut journal = GitJournal::new(path)?;
@@ -78,13 +50,10 @@ fn run() -> Result<(), Error> {
Some("prepare") => {
// Prepare a commit message before editing by the user
if let Some(sub_matches) = matches.subcommand_matches("prepare") {
- match journal.prepare(sub_matches.value_of("message").ok_or(Error::Cli)?,
+ match journal.prepare(sub_matches.value_of("message").ok_or(internal_error("Cli", "No 'message' provided"))?,
sub_matches.value_of("type")) {
Ok(()) => info!("Commit message prepared."),
- Err(error) => {
- error_and_exit("Commit message preparation failed",
- Error::GitJournal(error))
- }
+ Err(error) => error_and_exit("Commit message preparation failed", error)
}
}
}
@@ -109,17 +78,19 @@ fn run() -> Result<(), Error> {
Some("verify") => {
// Verify a commit message
if let Some(sub_matches) = matches.subcommand_matches("verify") {
- match journal.verify(sub_matches.value_of("message").ok_or(Error::Cli)?) {
+ match journal.verify(sub_matches.value_of("message").ok_or(internal_error("Cli", "No 'message' provided"))?) {
Ok(()) => info!("Commit message valid."),
- Err(error) => error_and_exit("Commit message invalid", Error::GitJournal(error)),
+ Err(error) => error_and_exit("Commit message invalid", error),
}
}
}
_ => {
// Get all values of the given CLI parameters with default values
- let revision_range = matches.value_of("revision_range").ok_or(Error::Cli)?;
- let tag_skip_pattern = matches.value_of("tag_skip_pattern").ok_or(Error::Cli)?;
- let tags_count = matches.value_of("tags_count").ok_or(Error::Cli)?;
+ let revision_range = matches.value_of("revision_range")
+ .ok_or(internal_error("Cli", "No 'revision_range' provided"))?;
+ let tag_skip_pattern = matches.value_of("tag_skip_pattern")
+ .ok_or(internal_error("Cli", "No 'task_skip_pattern' provided"))?;
+ let tags_count = matches.value_of("tags_count").ok_or(internal_error("Cli", "No 'tags_count' provided"))?;
let max_tags = tags_count.parse::<u32>()?;
// Parse the log
@@ -128,7 +99,7 @@ fn run() -> Result<(), Error> {
&max_tags,
&matches.is_present("all"),
&matches.is_present("skip_unreleased")) {
- error_and_exit("Log parsing error", Error::GitJournal(error));
+ error_and_exit("Log parsing error", error);
}
// Generate the template or print the log
diff --git a/src/parser.rs b/src/parser.rs
index 31cf2f2..bc79d30 100644
--- a/src/parser.rs
+++ b/src/parser.rs
@@ -3,18 +3,15 @@ use git2::Oid;
use nom::{IResult, alpha, digit, space, rest};
use regex::{Regex, RegexBuilder};
use term;
-use toml;
-use toml::Value;
+use toml::{self, Value};
use std::collections::BTreeMap;
-use std::fmt;
use std::fs::File;
use std::io::prelude::*;
-use std::io;
-use std::iter;
-use std::str;
+use std::{iter, str};
use config::Config;
+use errors::{GitJournalResult, internal_error};
pub static TOML_DEFAULT_KEY: &'static str = "default";
pub static TOML_FOOTERS_KEY: &'static str = "footers";
@@ -26,49 +23,6 @@ pub static TOML_ONCE_KEY: &'static str = "once";
pub static TOML_HEADER_KEY: &'static str = "header";
pub static TOML_FOOTER_KEY: &'static str = "footer";
-#[derive(Debug)]
-pub enum Error {
- CommitMessageLength,
- FooterParsing(String),
- Io(io::Error),
- ParagraphParsing(String),
- SummaryParsing(String),
- Terminal,
- Toml(toml::Error),
-}
-
-impl fmt::Display for Error {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- match *self {
- Error::CommitMessageLength => write!(f, "Commit message length too small."),
- Error::FooterParsing(ref line) => write!(f, "Footer parsing: '{}'", line),
- Error::Io(ref e) => write!(f, "Io: {}", e),
- Error::ParagraphParsing(ref line) => write!(f, "Paragraph parsing: '{}'", line),
- Error::SummaryParsing(ref line) => write!(f, "Summary parsing: '{}'", line),
- Error::Terminal => write!(f, "Could not print to terminal."),
- Error::Toml(ref e) => write!(f, "Toml: {}", e),
- }
- }
-}
-
-impl From<term::Error> for Error {
- fn from(_err: term::Error) -> Error {
- Error::Terminal
- }
-}
-
-impl From<io::Error> for Error {
- fn from(err: io::Error) -> Error {
- Error::Io(err)
- }
-}
-
-impl From<toml::Error> for Error {
- fn from(err: toml::Error) -> Error {
- Error::Toml(err)
- }
-}
-
#[derive(PartialEq)]
pub enum Printed {
Nothing,
@@ -83,12 +37,12 @@ pub trait Print {
c1: &F,
c2: &G,
c3: &H)
- -> Result<Printed, Error>
- where F: Fn(&mut T) -> Result<(), Error>,
- G: Fn(&mut T) -> Result<(), Error>,
- H: Fn(&mut T) -> Result<(), Error>;
+ -> GitJournalResult<Printed>
+ where F: Fn(&mut T) -> GitJournalResult<()>,
+ G: Fn(&mut T) -> GitJournalResult<()>,
+ H: Fn(&mut T) -> GitJournalResult<()>;
- fn print_default<T: Write>(&self, t: &mut T, config: &Config, tag: Option<&str>) -> Result<(), Error> {
+ fn print_default<T: Write>(&self, t: &mut T, config: &Config, tag: Option<&str>) -> GitJournalResult<()> {
self.print(t, config, tag, &|_| Ok(()), &|_| Ok(()), &|_| Ok(()))?;
Ok(())
}
@@ -97,7 +51,7 @@ pub trait Print {
mut t: &mut Box<term::StdoutTerminal>,
config: &Config,
tag: Option<&str>)
- -> Result<(), Error> {
+ -> GitJournalResult<()> {
self.print(&mut t,
config,
tag,
@@ -136,7 +90,7 @@ pub trait Print {
mut vec: &mut Vec<u8>,
config: &Config,
tag: Option<&str>)
- -> Result<(), Error> {
+ -> GitJournalResult<()> {
self.print_default_term(&mut term, config, tag)?;
self.print_default(&mut vec, config, tag)?;
Ok(())
@@ -167,10 +121,10 @@ pub struct ParsedTag {
}
impl ParsedTag {
- fn print<T: Write, F, G, H>(&self, t: &mut T, config: &Config, c1: &F, c2: &G, c3: &H) -> Result<Printed, Error>
- where F: Fn(&mut T) -> Result<(), Error>,
- G: Fn(&mut T) -> Result<(), Error>,
- H: Fn(&mut T) -> Result<(), Error>
+ fn print<T: Write, F, G, H>(&self, t: &mut T, config: &Config, c1: &F, c2: &G, c3: &H) -> GitJournalResult<Printed>
+ where F: Fn(&mut T) -> GitJournalResult<()>,
+ G: Fn(&mut T) -> GitJournalResult<()>,
+ H: Fn(&mut T) -> GitJournalResult<()>
{
if config.colored_output {
c1(t)?;
@@ -190,12 +144,12 @@ impl ParsedTag {
Ok(Printed::Something)
}
- fn print_default<T: Write>(&self, t: &mut T, config: &Config) -> Result<(), Error> {
+ fn print_default<T: Write>(&self, t: &mut T, config: &Config) -> GitJournalResult<()> {
self.print(t, config, &|_| Ok(()), &|_| Ok(()), &|_| Ok(()))?;
Ok(())
}
- fn print_default_term(&self, mut t: &mut Box<term::StdoutTerminal>, config: &Config) -> Result<(), Error> {
+ fn print_default_term(&self, mut t: &mut Box<term::StdoutTerminal>, config: &Config) -> GitJournalResult<()> {
self.print(&mut t,
config,
&|t| {
@@ -220,7 +174,7 @@ impl ParsedTag {
config: &Config,
template: Option<&str>,
index_len: (usize, usize))
- -> Result<(), Error> {
+ -> GitJournalResult<()> {
match template {
Some(template) => {
// Try to parse the template
@@ -294,7 +248,7 @@ impl ParsedTag {
level: &mut usize,
config: &Config,
compact: &bool)
- -> Result<(), Error> {
+ -> GitJournalResult<()> {
for value in table {
if let Value::Array(ref array) = *value.1 {
for item in array {
@@ -367,7 +321,7 @@ impl ParsedTag {
mut vec: &mut Vec<u8>,
footer_keys: Option<&[Value]>,
config: &Config)
- -> Result<(), Error> {
+ -> GitJournalResult<()> {
let mut footer_tree: BTreeMap<String, Vec<String>> = BTreeMap::new();
@@ -458,10 +412,10 @@ impl Print for ParsedCommit {
c1: &F,
c2: &G,
c3: &H)
- -> Result<Printed, Error>
- where F: Fn(&mut T) -> Result<(), Error>,
- G: Fn(&mut T) -> Result<(), Error>,
- H: Fn(&mut T) -> Result<(), Error>
+ -> GitJournalResult<Printed>
+ where F: Fn(&mut T) -> GitJournalResult<()>,
+ G: Fn(&mut T) -> GitJournalResult<()>,
+ H: Fn(&mut T) -> GitJournalResult<()>
{
// If summary is already filtered out then do not print at all
if self.summary.print(t, config, tag, c1, c2, c3)? == Printed::Nothing {
@@ -510,10 +464,10 @@ impl Print for SummaryElement {
c1: &F,
c2: &G,
c3: &H)
- -> Result<Printed, Error>
- where F: Fn(&mut T) -> Result<(), Error>,
- G: Fn(&mut T) -> Result<(), Error>,
- H: Fn(&mut T) -> Result<(), Error>
+ -> GitJournalResult<Printed>
+ where F: Fn(&mut T) -> GitJournalResult<()>,
+ G: Fn(&mut T) -> GitJournalResult<()>,
+ H: Fn(&mut T) -> GitJournalResult<()>
{
// Filter out excluded tags
if self.tags.iter().filter(|x| config.excluded_commit_tags.contains(x)).count() > 0usize {
@@ -589,10 +543,10 @@ impl Print for BodyElement {
c1: &F,
c2: &G,
c3: &H)
- -> Result<Printed, Error>
- where F: Fn(&mut T) -> Result<(), Error>,
- G: Fn(&mut T) -> Result<(), Error>,
- H: Fn(&mut T) -> Result<(), Error>
+ -> GitJournalResult<Printed>
+ where F: Fn(&mut T) -> GitJournalResult<()>,
+ G: Fn(&mut T) -> GitJournalResult<()>,
+ H: Fn(&mut T) -> GitJournalResult<()>
{
match *self {
BodyElement::List(ref vec) => {
@@ -644,10 +598,10 @@ impl Print for ListElement {
c1: &F,
c2: &G,
c3: &H)
- -> Result<Printed, Error>
- where F: Fn(&mut T) -> Result<(), Error>,
- G: Fn(&mut T) -> Result<(), Error>,
- H: Fn(&mut T) -> Result<(), Error>
+ -> GitJournalResult<Printed>
+ where F: Fn(&mut T) -> GitJournalResult<()>,
+ G: Fn(&mut T) -> GitJournalResult<()>,
+ H: Fn(&mut T) -> GitJournalResult<()>
{
// Check if list item contains excluded tag
if self.tags.iter().filter(|x| config.excluded_commit_tags.contains(x)).count() > 0usize {
@@ -713,10 +667,10 @@ impl Print for ParagraphElement {
_c1: &F,
_c2: &G,
_c3: &H)
- -> Result<Printed, Error>
- where F: Fn(&mut T) -> Result<(), Error>,
- G: Fn(&mut T) -> Result<(), Error>,
- H: Fn(&mut T) ->