From 61b9a338a5d502c5a5937aa6fed620f2fb941dc2 Mon Sep 17 00:00:00 2001 From: Joshua Potter Date: Sun, 2 Jan 2022 11:14:05 -0500 Subject: [PATCH] Add a logging solution, and remove ANSI crate. --- Cargo.toml | 5 +++-- src/config.rs | 17 ++++++++++------- src/daemon.rs | 38 +++++++++++++++++++++----------------- src/git.rs | 6 +++++- src/lib.rs | 2 +- src/main.rs | 16 ++++++++++++++-- 6 files changed, 54 insertions(+), 30 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index dd0041e..e62636f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,13 +10,14 @@ version = "0.1.0" edition = "2021" [dependencies] -ansi_term = "0.12.1" clap = { version = "3.0.0-rc.9", features = ["derive"] } git2 = "0.13.25" +log = "0.4.14" notify = "4.0.16" regex = "1.5.4" serde = "1.0" serde_derive = "1.0.132" serde_yaml = "0.8" -yaml-rust = "0.4.4" +simplelog = { version = "^0.11.1", features = ["paris"] } url = { version = "2.2.2", features = ["serde"] } +yaml-rust = "0.4.4" diff --git a/src/config.rs b/src/config.rs index aa9b999..a3379cc 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,6 +1,7 @@ use super::{path, path::ResPathBuf}; -use ansi_term::Colour::{Green, Yellow}; +use paris::formatter::colorize_string; use serde_derive::{Deserialize, Serialize}; +use simplelog::{info, paris}; use std::{ collections::BTreeMap, env::VarError, @@ -143,8 +144,10 @@ pub fn load(candidates: &Vec) -> Result { } pub fn reload(config: &PathConfig) -> Result { - // TODO(jrpotter): Let's add a proper logging solution. - println!("Configuration reloaded."); + info!( + "{} configuration reloaded.", + config.1.local.display() + ); load(&vec![config.0.clone()]) } @@ -156,7 +159,7 @@ fn prompt_local(path: Option<&Path>) -> Result { let default = path.map_or("$HOME/.homesync".to_owned(), |p| p.display().to_string()); print!( "Local git repository <{}> (enter to continue): ", - Yellow.paint(&default) + colorize_string(format!("{}", &default)), ); io::stdout().flush()?; let mut local = String::new(); @@ -176,7 +179,7 @@ fn prompt_remote(url: Option<&Url>) -> Result { }); print!( "Remote git repository <{}> (enter to continue): ", - Yellow.paint(&default) + colorize_string(format!("{}", &default)), ); io::stdout().flush()?; let mut remote = String::new(); @@ -192,7 +195,7 @@ fn prompt_remote(url: Option<&Url>) -> Result { pub fn write(path: &ResPathBuf, loaded: Option) -> Result { println!( "Generating config at {}...\n", - Green.paint(path.unresolved().display().to_string()) + colorize_string(format!("{}", path.unresolved().display())), ); let local = prompt_local(match &loaded { Some(c) => Some(c.local.as_ref()), @@ -221,7 +224,7 @@ pub fn write(path: &ResPathBuf, loaded: Option) -> Result { pub fn list_packages(config: PathConfig) { println!( "Listing packages in {}...\n", - Green.paint(config.0.unresolved().display().to_string()) + colorize_string(format!("{}", config.0.unresolved().display())), ); // Alphabetical ordered ensured by B-tree implementation. for (k, _) in config.1.packages { diff --git a/src/daemon.rs b/src/daemon.rs index 1c60d66..cd8695b 100644 --- a/src/daemon.rs +++ b/src/daemon.rs @@ -1,5 +1,6 @@ use super::{config, config::PathConfig, path, path::ResPathBuf}; use notify::{DebouncedEvent, RecommendedWatcher, RecursiveMode, Watcher}; +use simplelog::{error, paris, trace, warn}; use std::{ collections::HashSet, error::Error, @@ -9,7 +10,6 @@ use std::{ time::Duration, }; -// TODO(jrpotter): Add logging. // TODO(jrpotter): Add pid file to only allow one daemon at a time. // TODO(jrpotter): Sync files to local git repository. @@ -34,7 +34,7 @@ fn resolve_pending(tx: &Sender, pending: &HashSet) -> V Ok(None) => (), Err(e) => { to_remove.push(path.clone()); - eprintln!( + error!( "Encountered unexpected error {} when processing path {}", e, path.display() @@ -96,7 +96,7 @@ impl<'a> WatchState<'a> { self.watching.insert(path); } Err(e) => { - eprintln!( + error!( "Encountered unexpected error {} when watching path {}", e, path.unresolved().display() @@ -113,7 +113,7 @@ impl<'a> WatchState<'a> { match self.watcher.unwatch(&path) { Ok(()) => (), Err(e) => { - eprintln!( + error!( "Encountered unexpected error {} when unwatching path {}", e, path.unresolved().display() @@ -159,47 +159,51 @@ pub fn launch(mut config: PathConfig, freq_secs: u64) -> Result<(), Box { - // Intentionally ignore in favor of stronger signals. + Ok(DebouncedEvent::NoticeWrite(p)) => { + trace!("NoticeWrite {}", p.display()); } - Ok(DebouncedEvent::NoticeRemove(_)) => { - // Intentionally ignore in favor of stronger signals. + Ok(DebouncedEvent::NoticeRemove(p)) => { + trace!("NoticeRemove {}", p.display()); } Ok(DebouncedEvent::Create(p)) => { if config.0 == p { config = config::reload(&config)?; state.update(&config); } - println!("Create {}", p.display()); + trace!("Create {}", p.display()); } Ok(DebouncedEvent::Write(p)) => { if config.0 == p { config = config::reload(&config)?; state.update(&config); } - println!("Write {}", p.display()); + trace!("Write {}", p.display()); } // Do not try reloading our primary config in any of the following // cases since it may lead to undesired behavior. If our config has // e.g. been removed, let's just keep using what we have in memory // in the chance it may be added back. Ok(DebouncedEvent::Chmod(p)) => { - println!("Chmod {}", p.display()); + trace!("Chmod {}", p.display()); } Ok(DebouncedEvent::Remove(p)) => { - println!("Remove {}", p.display()); + trace!("Remove {}", p.display()); } Ok(DebouncedEvent::Rename(src, dst)) => { - println!("Rename {} {}", src.display(), dst.display()) + trace!("Rename {} {}", src.display(), dst.display()) } Ok(DebouncedEvent::Rescan) => { - println!("Rescanning"); + trace!("Rescanning"); } - Ok(DebouncedEvent::Error(e, _maybe_path)) => { - println!("Error {}", e); + Ok(DebouncedEvent::Error(e, path)) => { + warn!( + "Error {} at {}", + e, + path.unwrap_or_else(|| PathBuf::from("N/A")).display() + ); } Err(e) => { - println!("watch error: {:?}", e); + error!("Watch error: {:?}", e); } } } diff --git a/src/git.rs b/src/git.rs index d697ff7..297a072 100644 --- a/src/git.rs +++ b/src/git.rs @@ -1,5 +1,6 @@ use super::{config::PathConfig, path}; use git2::Repository; +use simplelog::{info, paris}; use std::{env::VarError, error, fmt, fs, io, path::PathBuf, result}; // ======================================== @@ -143,7 +144,10 @@ pub fn init(config: &PathConfig) -> Result { // issues that we need to resolve anyways (e.g. setting remote, pulling, // managing possible merge conflicts, etc.). None => { - println!("Creating new homesync repository."); + info!( + "Creating new homesync repository at {}.", + config.1.local.display() + ); let repo = Repository::init(&expanded)?; fs::File::create(sentinel)?; Ok(repo) diff --git a/src/lib.rs b/src/lib.rs index 564f3fd..98d8b9e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -45,7 +45,7 @@ pub fn run_init(candidates: Vec) -> Result<(), Box> { // git library we chose to use employs async/await so let's wrap around a // channel. git::init(&config)?; - println!("Finished initialization."); + println!("\nFinished initialization."); Ok(()) } diff --git a/src/main.rs b/src/main.rs index 192ee28..b616d79 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,8 +1,20 @@ use clap::{App, AppSettings, Arg}; use homesync::path::ResPathBuf; +use simplelog; +use simplelog::{error, paris}; use std::{error::Error, io, path::PathBuf}; fn main() { + // Only one logger should ever be initialized and it should be done at the + // beginning of the program. Otherwise logs are ignored. + simplelog::TermLogger::init( + simplelog::LevelFilter::Info, + simplelog::Config::default(), + simplelog::TerminalMode::Mixed, + simplelog::ColorChoice::Auto, + ) + .expect("Could not initialize logger library."); + let matches = App::new("homesync") .about("Cross desktop configuration sync tool.") .version("0.1.0") @@ -43,7 +55,7 @@ fn main() { .get_matches(); if let Err(e) = dispatch(matches) { - eprintln!("{}", e); + error!("{}", e); } } @@ -68,7 +80,7 @@ fn dispatch(matches: clap::ArgMatches) -> Result<(), Box> { if freq_secs > 0 { homesync::run_daemon(config, freq_secs)?; } else { - eprintln!("Invalid frequency. Expected a positive integer."); + error!("Invalid frequency. Expected a positive integer."); } Ok(()) }