diff options
author | Sascha Grunert <Sascha.Grunert@rohde-schwarz.com> | 2016-10-25 10:25:20 +0200 |
---|---|---|
committer | Sascha Grunert <Sascha.Grunert@rohde-schwarz.com> | 2016-10-25 10:25:20 +0200 |
commit | c602b125473833f114a97dd7d3079339ed194381 (patch) | |
tree | 58a29046fa1c1dd3ba8dbb3adb06d3e3ca2340f4 | |
parent | 0e90cd48c0107a7934b736590cda1ded91a10c93 (diff) |
Improved logging facade
-rw-r--r-- | .gitjournal.toml | 2 | ||||
-rw-r--r-- | Cargo.lock | 31 | ||||
-rw-r--r-- | Cargo.toml | 1 | ||||
-rw-r--r-- | git-journal.fish | 95 | ||||
-rw-r--r-- | src/lib.rs | 115 | ||||
-rw-r--r-- | src/logger.rs | 55 | ||||
-rw-r--r-- | src/macros.rs | 41 | ||||
-rw-r--r-- | src/main.rs | 58 | ||||
-rw-r--r-- | src/parser.rs | 12 |
9 files changed, 196 insertions, 214 deletions
diff --git a/.gitjournal.toml b/.gitjournal.toml index 508a97e..0f34c51 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 = "" +template_prefix = "JIRA-1234" @@ -3,9 +3,10 @@ name = "git-journal" version = "1.0.0" dependencies = [ "chrono 0.2.25 (registry+https://github.com/rust-lang/crates.io-index)", - "clap 2.14.0 (registry+https://github.com/rust-lang/crates.io-index)", + "clap 2.16.1 (registry+https://github.com/rust-lang/crates.io-index)", "git2 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "nom 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "rayon 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.1.77 (registry+https://github.com/rust-lang/crates.io-index)", @@ -43,7 +44,7 @@ dependencies = [ [[package]] name = "clap" -version = "2.14.0" +version = "2.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -62,7 +63,7 @@ name = "cmake" version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "gcc 0.3.37 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -70,7 +71,7 @@ name = "curl-sys" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "gcc 0.3.37 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", "libz-sys 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-sys 0.7.17 (registry+https://github.com/rust-lang/crates.io-index)", @@ -88,7 +89,7 @@ dependencies = [ [[package]] name = "gcc" -version = "0.3.37" +version = "0.3.38" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -108,7 +109,7 @@ dependencies = [ "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", "libgit2-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -147,7 +148,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cmake 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", "curl-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "gcc 0.3.37 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", "libssh2-sys 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", "libz-sys 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -180,12 +181,17 @@ name = "libz-sys" version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "gcc 0.3.37 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] +name = "log" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] name = "matches" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -404,7 +410,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "url" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "idna 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -450,11 +456,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23ac7c30002a5accbf7e8987d0632fa6de155b7c3d39d0067317a391e00a2ef6" "checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d" "checksum chrono 0.2.25 (registry+https://github.com/rust-lang/crates.io-index)" = "9213f7cd7c27e95c2b57c49f0e69b1ea65b27138da84a170133fd21b07659c00" -"checksum clap 2.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5fa304b03c49ccbb005784fc26e985b5d2310b1d37f2c311ce90dbcd18ea5fde" +"checksum clap 2.16.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7d3f517329dfa6300c8415693c54e524f777dc470265bd73dfd1ff1699c3ee30" "checksum cmake 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "dfcf5bcece56ef953b8ea042509e9dcbdfe97820b7e20d86beb53df30ed94978" "checksum curl-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4ae8698d4d2bc4b8182a11f4a5298fa03d2127c29e95dbae538d0cf003141818" "checksum deque 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1614659040e711785ed8ea24219140654da1729f3ec8a47a9719d041112fe7bf" -"checksum gcc 0.3.37 (registry+https://github.com/rust-lang/crates.io-index)" = "41337e9dc80ebadf36b4f252bf7440f61bcf34f99caa170e50dcd0f9a0cdb5d8" +"checksum gcc 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)" = "553f11439bdefe755bf366b264820f1da70f3aaf3924e594b886beb9c831bcf5" "checksum gdi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0912515a8ff24ba900422ecda800b52f4016a56251922d397c576bf92c690518" "checksum git2 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f6419fd6f609a1a2fbbee5dffdb2c26e8e5cd0c06d558d17d3381187e03bbe18" "checksum idna 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1053236e00ce4f668aeca4a769a09b3bf5a682d802abd6f3cb39374f6b162c11" @@ -465,6 +471,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum libressl-pnacl-sys 2.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "cbc058951ab6a3ef35ca16462d7642c4867e6403520811f28537a4e2f2db3e71" "checksum libssh2-sys 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "1debd7e56d19655eb786f827675dc55f6d530de6d7b81e76d13d1afc635d6c07" "checksum libz-sys 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "40f2df7730b5d29426c3e44ce4d088d8c5def6471c2c93ba98585b89fb201ce6" +"checksum log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ab83497bf8bf4ed2a74259c1c802351fcd67a65baa86394b6ba73c36f4838054" "checksum matches 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bcc3ad8109fa4b522f9b0cd81440422781f564aaf8c195de6b9d6642177ad0dd" "checksum memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d8b629fb514376c675b98c1421e80b151d3817ac42d7c667717d282761418d20" "checksum nom 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a5b8c256fd9471521bcb84c3cdba98921497f1a331cbc15b8030fc63b82050ce" @@ -493,7 +500,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum unicode-normalization 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "26643a2f83bac55f1976fb716c10234485f9202dcd65cfbdf9da49867b271172" "checksum unicode-segmentation 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b905d0fc2a1f0befd86b0e72e31d1787944efef9d38b9358a9e92a69757f7e3b" "checksum unicode-width 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2d6722facc10989f63ee0e20a83cd4e1714a9ae11529403ac7e0afd069abc39e" -"checksum url 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8527c62d9869a08325c38272b3f85668df22a65890c61a639d233dc0ed0b23a2" +"checksum url 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9ba5a45db1d2e0effb7a1c00cc73ffc63a973da8c7d1fcd5b46f24285ade6c54" "checksum user32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ef4711d107b21b410a3a974b1204d9accc8b10dad75d8324b5d755de1617d47" "checksum utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a1ca13c08c41c9c3e04224ed9ff80461d97e121589ff27c753a16cb10830ae0f" "checksum vec_map 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cac5efe5cb0fa14ec2f84f83c701c562ee63f6dcc680861b21d65c682adfb05f" @@ -18,6 +18,7 @@ chrono = "0" clap = { version = "2", features = ["yaml"] } git2 = "0" lazy_static = "0" +log = "0" nom = { version = "1", features = ["regexp_macros"] } regex = "0" rayon = "0" diff --git a/git-journal.fish b/git-journal.fish index 60ebb12..af1a8f5 100644 --- a/git-journal.fish +++ b/git-journal.fish @@ -1,52 +1,49 @@ -function __fish_git-journal_no_subcommand --description "Test if there isn't given a subcommand" - for i in (commandline -opc) - if contains -- $i help p prepare s setup v verify - return 1 +function __fish_using_command + set cmd (commandline -opc) + if [ (count $cmd) -eq (count $argv) ] + for i in (seq (count $argv)) + if [ $cmd[$i] != $argv[$i] ] + return 1 + end end + return 0 end - return 0 + return 1 end -complete -c git-journal -n '__fish_git-journal_no_subcommand' -s p -l path -d 'Sets a custom working path.' -complete -c git-journal -n '__fish_git-journal_no_subcommand' -s n -l tags-count -d 'The number of tags until the parser stops when a single revision is given.' -complete -c git-journal -n '__fish_git-journal_no_subcommand' -s e -d 'A pattern to exclude git tags from the processing.' -complete -c git-journal -n '__fish_git-journal_no_subcommand' -s t -l template -d 'Use a custom output template.' -complete -c git-journal -n '__fish_git-journal_no_subcommand' -s o -l output -d 'The output file for the changelog.' -complete -c git-journal -n '__fish_git-journal_no_subcommand' -s a -l all -d 'Do not stop parsing at the first tag when a single revision is given. Overwrites '-n/--tags-count'.' -complete -c git-journal -n '__fish_git-journal_no_subcommand' -s g -l generate -d 'Generate a fresh output template from a commit range.' -complete -c git-journal -n '__fish_git-journal_no_subcommand' -s s -l short -d 'Print only the shortlog (summary) form.' -complete -c git-journal -n '__fish_git-journal_no_subcommand' -s u -l skip-unreleased -d 'Skip entries without any relation to a git TAG.' -complete -c git-journal -n '__fish_git-journal_no_subcommand' -s h -l help -d 'Prints help information' -complete -c git-journal -n '__fish_git-journal_no_subcommand' -s V -l version -d 'Prints version information' -complete -c git-journal -n '__fish_git-journal_no_subcommand' -s h -l help -d 'Prints help information' -complete -c git-journal -n '__fish_git-journal_no_subcommand' -s V -l version -d 'Prints version information' -complete -c git-journal -n '__fish_git-journal_no_subcommand' -f -a 'help' -complete -c git-journal -n '__fish_git-journal_no_subcommand' -f -a 'p' -complete -c git-journal -n '__fish_git-journal_no_subcommand' -f -a 'prepare' -complete -c git-journal -n '__fish_git-journal_no_subcommand' -f -a 's' -complete -c git-journal -n '__fish_git-journal_no_subcommand' -f -a 'setup' -complete -c git-journal -n '__fish_git-journal_no_subcommand' -f -a 'v' -complete -c git-journal -n '__fish_git-journal_no_subcommand' -f -a 'verify' -complete -c git-journal -n '__fish_seen_subcommand_from prepare' -s h -l help -d 'Prints help information' -complete -c git-journal -n '__fish_seen_subcommand_from prepare' -s V -l version -d 'Prints version information' -complete -c git-journal -n '__fish_seen_subcommand_from prepare' -s h -l help -d 'Prints help information' -complete -c git-journal -n '__fish_seen_subcommand_from prepare' -s V -l version -d 'Prints version information' -complete -c git-journal -n '__fish_seen_subcommand_from prepare' -f -a 'prepare' -complete -c git-journal -n '__fish_seen_subcommand_from p' -f -a 'p' -complete -c git-journal -n '__fish_seen_subcommand_from setup' -s h -l help -d 'Prints help information' -complete -c git-journal -n '__fish_seen_subcommand_from setup' -s V -l version -d 'Prints version information' -complete -c git-journal -n '__fish_seen_subcommand_from setup' -s h -l help -d 'Prints help information' -complete -c git-journal -n '__fish_seen_subcommand_from setup' -s V -l version -d 'Prints version information' -complete -c git-journal -n '__fish_seen_subcommand_from setup' -f -a 'setup' -complete -c git-journal -n '__fish_seen_subcommand_from s' -f -a 's' -complete -c git-journal -n '__fish_seen_subcommand_from verify' -s h -l help -d 'Prints help information' -complete -c git-journal -n '__fish_seen_subcommand_from verify' -s V -l version -d 'Prints version information' -complete -c git-journal -n '__fish_seen_subcommand_from verify' -s h -l help -d 'Prints help information' -complete -c git-journal -n '__fish_seen_subcommand_from verify' -s V -l version -d 'Prints version information' -complete -c git-journal -n '__fish_seen_subcommand_from verify' -f -a 'verify' -complete -c git-journal -n '__fish_seen_subcommand_from v' -f -a 'v' -complete -c git-journal -n '__fish_seen_subcommand_from help' -s h -l help -d 'Prints help information' -complete -c git-journal -n '__fish_seen_subcommand_from help' -s V -l version -d 'Prints version information' -complete -c git-journal -n '__fish_seen_subcommand_from help' -s h -l help -d 'Prints help information' -complete -c git-journal -n '__fish_seen_subcommand_from help' -s V -l version -d 'Prints version information' -complete -c git-journal -n '__fish_seen_subcommand_from help' -s h -l help -d 'Prints help information' -complete -c git-journal -n '__fish_seen_subcommand_from help' -s V -l version -d 'Prints version information' + +complete -c git-journal -n '__fish_using_command git-journal' -s p -l path -d 'Sets a custom working path.' +complete -c git-journal -n '__fish_using_command git-journal' -s n -l tags-count -d 'The number of tags until the parser stops when a single revision is given.' +complete -c git-journal -n '__fish_using_command git-journal' -s e -d 'A pattern to exclude git tags from the processing.' +complete -c git-journal -n '__fish_using_command git-journal' -s t -l template -d 'Use a custom output template.' +complete -c git-journal -n '__fish_using_command git-journal' -s o -l output -d 'The output file for the changelog.' +complete -c git-journal -n '__fish_using_command git-journal' -s a -l all -d 'Do not stop parsing at the first tag when a single revision is given. Overwrites '-n/--tags-count'.' +complete -c git-journal -n '__fish_using_command git-journal' -s g -l generate -d 'Generate a fresh output template from a commit range.' +complete -c git-journal -n '__fish_using_command git-journal' -s s -l short -d 'Print only the shortlog (summary) form.' +complete -c git-journal -n '__fish_using_command git-journal' -s u -l skip-unreleased -d 'Skip entries without any relation to a git TAG.' +complete -c git-journal -n '__fish_using_command git-journal' -s h -l help -d 'Prints help information' +complete -c git-journal -n '__fish_using_command git-journal' -s V -l version -d 'Prints version information' +complete -c git-journal -n '__fish_using_command git-journal' -s h -l help -d 'Prints help information' +complete -c git-journal -n '__fish_using_command git-journal' -s V -l version -d 'Prints version information' +complete -c git-journal -n '__fish_using_command git-journal' -f -a 'prepare' +complete -c git-journal -n '__fish_using_command git-journal' -f -a 'setup' +complete -c git-journal -n '__fish_using_command git-journal' -f -a 'verify' +complete -c git-journal -n '__fish_using_command git-journal' -f -a 'help' +complete -c git-journal -n '__fish_using_command git-journal' -f -a 'help' +complete -c git-journal -n '__fish_using_command git-journal prepare' -s h -l help -d 'Prints help information' +complete -c git-journal -n '__fish_using_command git-journal prepare' -s V -l version -d 'Prints version information' +complete -c git-journal -n '__fish_using_command git-journal prepare' -s h -l help -d 'Prints help information' +complete -c git-journal -n '__fish_using_command git-journal prepare' -s V -l version -d 'Prints version information' +complete -c git-journal -n '__fish_using_command git-journal setup' -s h -l help -d 'Prints help information' +complete -c git-journal -n '__fish_using_command git-journal setup' -s V -l version -d 'Prints version information' +complete -c git-journal -n '__fish_using_command git-journal setup' -s h -l help -d 'Prints help information' +complete -c git-journal -n '__fish_using_command git-journal setup' -s V -l version -d 'Prints version information' +complete -c git-journal -n '__fish_using_command git-journal verify' -s h -l help -d 'Prints help information' +complete -c git-journal -n '__fish_using_command git-journal verify' -s V -l version -d 'Prints version information' +complete -c git-journal -n '__fish_using_command git-journal verify' -s h -l help -d 'Prints help information' +complete -c git-journal -n '__fish_using_command git-journal verify' -s V -l version -d 'Prints version information' +complete -c git-journal -n '__fish_using_command git-journal help' -s h -l help -d 'Prints help information' +complete -c git-journal -n '__fish_using_command git-journal help' -s V -l version -d 'Prints version information' +complete -c git-journal -n '__fish_using_command git-journal help' -s h -l help -d 'Prints help information' +complete -c git-journal -n '__fish_using_command git-journal help' -s V -l version -d 'Prints version information' +complete -c git-journal -n '__fish_using_command git-journal help' -s h -l help -d 'Prints help information' +complete -c git-journal -n '__fish_using_command git-journal help' -s V -l version -d 'Prints version information' @@ -36,11 +36,16 @@ extern crate nom; #[macro_use] extern crate lazy_static; +#[macro_use] +extern crate log; + use chrono::{UTC, TimeZone}; use git2::{ObjectType, Oid, Repository}; +use log::{LogLevelFilter, SetLoggerError}; use rayon::prelude::*; use toml::Value; +use logger::Logger; use parser::{Parser, ParsedTag, Tags}; pub use config::Config; @@ -50,8 +55,7 @@ use std::fs::{File, OpenOptions}; use std::path::{Path, PathBuf}; use std::io::prelude::*; -#[macro_use] -mod macros; +mod logger; mod parser; pub mod config; @@ -64,15 +68,15 @@ pub enum Error { /// Erros related to the system IO, like parsing of the configuration file. Io(std::io::Error), + /// Erros related to the logging system. + Logger(SetLoggerError), + /// 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 terminal emulation, which is used for colored output. - Term(term::Error), - /// Errors related to the commit message verification. Verify(String), } @@ -89,12 +93,6 @@ impl From<std::io::Error> for Error { } } -impl From<term::Error> for Error { - fn from(err: term::Error) -> Error { - Error::Term(err) - } -} - impl From<config::Error> for Error { fn from(err: config::Error) -> Error { Error::Setup(err) @@ -107,14 +105,20 @@ impl From<parser::Error> for Error { } } +impl From<SetLoggerError> for Error { + fn from(err: SetLoggerError) -> Error { + Error::Logger(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::Logger(ref err) => write!(f, "Logger: {}", err), Error::Parser(ref err) => write!(f, "Parser: {}", err), Error::Setup(ref err) => write!(f, "Setup: {}", err), - Error::Term(ref err) => write!(f, "Term: {}", err), Error::Verify(ref err) => write!(f, "Verify: {}", err), } } @@ -181,7 +185,7 @@ impl GitJournal { // Search for config in path and load let mut new_config = Config::new(); if let Err(e) = new_config.load(path) { - println_warn!("Can't load configuration file, using default one: {}", e); + warn!("Can't load configuration file, using default one: {}", e); } // Create a new parser with empty results @@ -190,6 +194,14 @@ impl GitJournal { result: vec![], }; + // Setup the logger + if new_config.enable_debug { + try!(log::set_logger(|max_log_level| { + max_log_level.set(LogLevelFilter::Info); + Box::new(Logger) + })); + } + // Return the git journal object Ok(GitJournal { config: new_config, @@ -259,9 +271,7 @@ impl GitJournal { pub fn setup(&self) -> Result<(), Error> { // Save the default config let output_file = try!(Config::new().save_default_config(&self.path)); - if self.config.enable_debug { - println_ok!("Defaults written to '{}' file.", output_file); - } + info!("Defaults written to '{}' file.", output_file); // Install commit message hook try!(self.install_git_hook("commit-msg", "git journal v $1\n")); @@ -278,18 +288,14 @@ impl GitJournal { hook_path.push(name); let mut hook_file: File; if hook_path.exists() { - if self.config.enable_debug { - println_warn!("There is already a hook available in '{}'. Please verifiy \ - the hook by hand after the installation.", - hook_path.display()); - } + warn!("There is already a hook available in '{}'. Please verifiy \ + the hook by hand after the installation.", + hook_path.display()); hook_file = try!(OpenOptions::new().read(true).append(true).open(&hook_path)); let mut hook_content = String::new(); try!(hook_file.read_to_string(&mut hook_content)); if hook_content.contains(content) { - if self.config.enable_debug { - println_ok!("Hook already installed, nothing changed in existing hook."); - } + info!("Hook already installed, nothing changed in existing hook."); return Ok(()); } } else { @@ -299,9 +305,7 @@ impl GitJournal { try!(hook_file.write_all(content.as_bytes())); try!(self.chmod(&hook_path, 0o755)); - if self.config.enable_debug { - println_ok!("Git hook installed to '{}'.", hook_path.display()); - } + info!("Git hook installed to '{}'.", hook_path.display()); Ok(()) } @@ -420,10 +424,8 @@ impl GitJournal { 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() { - if self.config.enable_debug { - println_warn!("These tags are not part of the default template: '{}'.", - invalid_tags.join(", ")); - } + 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())); } } @@ -539,20 +541,7 @@ impl GitJournal { Ok(parsed_message) => { *result = Some(parsed_message); } - Err(e) => { - if self.config.enable_debug { - if let Some(mut t) = term::stderr() { - // Since this part is not important for production we - // skip the error handling here. - t.fg(term::color::YELLOW).is_ok(); - write!(t, "[git-journal] ").is_ok(); - t.fg(term::color::BRIGHT_BLUE).is_ok(); - write!(t, "[INFO] ").is_ok(); - t.reset().is_ok(); - writeln!(t, "Skipping commit: {}.", e).is_ok(); - } - } - } + Err(e) => warn!("Skipping commit: {}.", e), } }); @@ -578,11 +567,8 @@ impl GitJournal { }) .collect::<Vec<ParsedTag>>(); - if self.config.enable_debug { - println_ok!("Parsing done. Processed {} commit messages.", - worker_vec.len()); - } - + info!("Parsing done. Processed {} commit messages.", + worker_vec.len()); Ok(()) } @@ -609,12 +595,10 @@ impl GitJournal { tags = parsed_tag.get_tags_unique(tags); } - if self.config.enable_debug { - if tags.len() > 1 { - println_ok!("Found tags: '{}'.", tags[1..].join(", ")); - } else { - println_warn!("No tags found."); - } + if tags.len() > 1 { + info!("Found tags: '{}'.", tags[1..].join(", ")); + } else { + warn!("No tags found."); } // Create the toml representation @@ -649,10 +633,7 @@ impl GitJournal { let mut toml_file = try!(File::create(&path_buf)); try!(toml_file.write_all(toml_string.as_bytes())); - if self.config.enable_debug { - println_ok!("Template written to '{}'", path_buf.display()); - } - + info!("Template written to '{}'", path_buf.display()); Ok(()) } @@ -684,15 +665,11 @@ impl GitJournal { match template { None => { if default_template.exists() { - if self.config.enable_debug { - println_ok!("Using default template '{}'.", default_template.display()); - } + info!("Using default template '{}'.", default_template.display()); default_template.to_str() } else { - if self.config.enable_debug { - println_warn!("The default template '{}' does not exist.", - default_template.display()); - } + warn!("The default template '{}' does not exist.", + default_template.display()); None } } @@ -709,9 +686,7 @@ impl GitJournal { if let Some(output) = output { let mut output_file = try!(OpenOptions::new().create(true).append(true).open(output)); try!(output_file.write_all(&output_vec)); - if self.config.enable_debug { - println_ok!("Output written to '{}'.", output); - } + info!("Output written to '{}'.", output); } Ok(()) diff --git a/src/logger.rs b/src/logger.rs new file mode 100644 index 0000000..4abb35c --- /dev/null +++ b/src/logger.rs @@ -0,0 +1,55 @@ +//! The logger implementation +use log::{Log, LogRecord, LogLevel, LogMetadata}; +use term; + +/// The logging structure +pub struct Logger; + +impl Log for Logger { + fn enabled(&self, metadata: &LogMetadata) -> bool { + metadata.level() <= LogLevel::Info + } + + fn log(&self, record: &LogRecord) { + if self.enabled(record.metadata()) { + if let Err(e) = self.log_result(record) { + println!("Error printing to log: {}", e); + } + } + } +} + +impl Logger { + fn log_result(&self, record: &LogRecord) -> Result<(), term::Error> { + // 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 = try!(term::stderr().ok_or(term::Error::NotSupported)); + try!(t.fg(term::color::BRIGHT_BLUE)); + try!(write!(t, "[git-journal] ")); + match record.level() { + LogLevel::Info => { + try!(t.fg(term::color::GREEN)); + try!(write!(t, "[OKAY] ")); + try!(t.reset()); + try!(writeln!(t, "{}", record.args())); + } + LogLevel::Warn => { + try!(t.fg(term::color::BRIGHT_YELLOW)); + try!(write!(t, "[WARN] ")); + try!(t.reset()); + try!(writeln!(t, "{}", record.args())); + } + LogLevel::Error => { + try!(t.fg(term::color::RED)); + try!(write!(t, "[ERROR] ")); + try!(t.reset()); + try!(writeln!(t, "{}", record.args())); + } + _ => { + try!(writeln!(t, "[{}] {}", record.level(), record.args())); + } + } + Ok(()) + } +} diff --git a/src/macros.rs b/src/macros.rs deleted file mode 100644 index e36ee20..0000000 --- a/src/macros.rs +++ /dev/null @@ -1,41 +0,0 @@ -macro_rules! println_color_category( - ($color:expr, $text:tt, $($arg:tt)*) => {{ - let mut t = try!(term::stderr().ok_or(term::Error::NotSupported)); - try!(t.fg(term::color::YELLOW)); - try!(write!(t, "[git-journal] ")); - try!(t.fg($color)); - try!(write!(t, "[{}] ", $text)); - try!(t.reset()); - try!(writeln!(t, $($arg)*)); - }} -); - -macro_rules! println_ok( - ($($arg:tt)*) => {{ - println_color_category!(term::color::BRIGHT_GREEN, "OKAY", $($arg)*); - }} -); - -macro_rules! println_info( - ($($arg:tt)*) => {{ - println_color_category!(term::color::BRIGHT_BLUE, "INFO", $($arg)*); - }} -); - -macro_rules! println_warn( - ($($arg:tt)*) => {{ - println_color_category!(term::color::BRIGHT_YELLOW, "WARN", $($arg)*); - }} -); - -macro_rules! trywln( - ($($arg:tt)*) => {{ - try!(writeln!($($arg)*)); - }} -); - -macro_rules! tryw( - ($($arg:tt)*) => {{ - try!(write!($($arg)*)); - }} -); diff --git a/src/main.rs b/src/main.rs index aa1b0c6..aca5b56 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,42 +1,25 @@ +extern crate gitjournal; + #[macro_use] extern crate clap; -extern crate gitjournal; -extern crate term; -use std::env; -use std::fmt; -use std::fs; +#[macro_use] +extern crate log; + use std::process::exit; +use std::{env, fmt, fs}; use clap::{App, Shell}; use gitjournal::GitJournal; -fn print_colored(string: &str, prefix: &str, color: term::color::Color) -> Result<(), term::Error> { - let mut t = try!(term::stderr().ok_or(term::Error::NotSupported)); - try!(t.fg(term::color::YELLOW)); - try!(write!(t, "[git-journal] ")); - try!(t.fg(color)); - try!(write!(t, "[{}] ", prefix)); - try!(t.reset()); - try!(writeln!(t, "{}", string)); - Ok(()) -} - -fn print_ok(string: &str) -> Result<(), term::Error> { - try!(print_colored(string, "OKAY", term::color::GREEN)); - Ok(()) -} - -fn print_err_exit(string: &str, error: Error) -> Result<(), term::Error> { - let format_string = format!("{}: {}", string, error); - try!(print_colored(&format_string, "ERROR", term::color::RED)); +fn error_and_exit(string: &str, error: Error) { + error!("{}: {}", string, error); exit(1); } enum Error { Cli, ParseInt(std::num::ParseIntError), - Term(term::Error), GitJournal(gitjournal::Error), } @@ -46,12 +29,6 @@ impl From<gitjournal::Error> for Error { } } -impl From<term::Error> for Error { - fn from(err: term::Error) -> Error { - Error::Term(err) - } -} - impl From<std::num::ParseIntError> for Error { fn from(err: std::num::ParseIntError) -> Error { Error::ParseInt(err) @@ -63,7 +40,6 @@ impl fmt::Display for Error { match *self { Error::Cli => write!(f, "Cli argument parsing"), Error::ParseInt(ref err) => write!(f, "ParseInt: {}", err), - Error::Term(ref err) => write!(f, "Term: {}", err), Error::GitJournal(ref err) => write!(f, "GitJournal: {}", err), } } @@ -83,7 +59,7 @@ fn is_program_in_path(program: &str) -> bool { fn main() { if let Err(error) = run() { - print_err_exit("Main", error).expect("Cannot print error message"); + error_and_exit("Main", error); } } @@ -104,10 +80,10 @@ fn run() -> Result<(), Error> { if let Some(sub_matches) = matches.subcommand_matches("prepare") { match journal.prepare(try!(sub_matches.value_of("message").ok_or(Error::Cli)), sub_matches.value_of("type")) { - Ok(()) => try!(print_ok("Commit message prepared.")), + Ok(()) => info!("Commit message prepared."), Err(error) => { - try!(print_err_exit("Commit message preparation failed", - Error::GitJournal(error))) + error_and_exit("Commit message preparation failed", + Error::GitJournal(error)) } } } @@ -119,19 +95,19 @@ fn run() -> Result<(), Error> { // Generate completions if necessary if is_program_in_path("bash") { app.gen_completions("git-journal", Shell::Bash, path); - try!(print_ok("Installed bash completions to the current path.")); + info!("Installed bash completions to the current path."); } if is_program_in_path("fish") { app.gen_completions("git-journal", Shell::Fish, path); - try!(print_ok("Installed fish completions to the current path.")); + info!("Installed fish completions to the current path."); } } Some("verify") => { // Verify a commit message if let Some(sub_matches) = matches.subcommand_matches("verify") { match journal.verify(try!(sub_matches.value_of("message").ok_or(Error::Cli))) { - Ok(()) => try!(print_ok("Commit message valid.")), - Err(error) => try!(print_err_exit("Commit message invalid", Error::GitJournal(error))), + Ok(()) => info!("Commit message valid."), + Err(error) => error_and_exit("Commit message invalid", Error::GitJournal(error)), } } } @@ -148,7 +124,7 @@ fn run() -> Result<(), Error> { &max_tags, &matches.is_present("all"), &matches.is_present("skip_unreleased")) { - try!(print_err_exit("Log parsing error", Error::GitJournal(error))); + error_and_exit("Log parsing error", Error::GitJournal(error)); } // Generate the template or print the log |