Add a logging solution, and remove ANSI crate.
parent
2c95c43124
commit
61b9a338a5
|
@ -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"
|
||||
|
|
|
@ -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<ResPathBuf>) -> Result<PathConfig> {
|
|||
}
|
||||
|
||||
pub fn reload(config: &PathConfig) -> Result<PathConfig> {
|
||||
// TODO(jrpotter): Let's add a proper logging solution.
|
||||
println!("Configuration reloaded.");
|
||||
info!(
|
||||
"<green>{}</> configuration reloaded.",
|
||||
config.1.local.display()
|
||||
);
|
||||
load(&vec![config.0.clone()])
|
||||
}
|
||||
|
||||
|
@ -156,7 +159,7 @@ fn prompt_local(path: Option<&Path>) -> Result<PathBuf> {
|
|||
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!("<yellow>{}</>", &default)),
|
||||
);
|
||||
io::stdout().flush()?;
|
||||
let mut local = String::new();
|
||||
|
@ -176,7 +179,7 @@ fn prompt_remote(url: Option<&Url>) -> Result<Url> {
|
|||
});
|
||||
print!(
|
||||
"Remote git repository <{}> (enter to continue): ",
|
||||
Yellow.paint(&default)
|
||||
colorize_string(format!("<yellow>{}</>", &default)),
|
||||
);
|
||||
io::stdout().flush()?;
|
||||
let mut remote = String::new();
|
||||
|
@ -192,7 +195,7 @@ fn prompt_remote(url: Option<&Url>) -> Result<Url> {
|
|||
pub fn write(path: &ResPathBuf, loaded: Option<Config>) -> Result<PathConfig> {
|
||||
println!(
|
||||
"Generating config at {}...\n",
|
||||
Green.paint(path.unresolved().display().to_string())
|
||||
colorize_string(format!("<green>{}</>", 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<Config>) -> Result<PathConfig> {
|
|||
pub fn list_packages(config: PathConfig) {
|
||||
println!(
|
||||
"Listing packages in {}...\n",
|
||||
Green.paint(config.0.unresolved().display().to_string())
|
||||
colorize_string(format!("<green>{}</>", config.0.unresolved().display())),
|
||||
);
|
||||
// Alphabetical ordered ensured by B-tree implementation.
|
||||
for (k, _) in config.1.packages {
|
||||
|
|
|
@ -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<DebouncedEvent>, pending: &HashSet<PathBuf>) -> 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<dyn Erro
|
|||
// Received paths should always be the fully resolved ones so safe to
|
||||
// compare against our current config path.
|
||||
match watch_rx.recv() {
|
||||
Ok(DebouncedEvent::NoticeWrite(_)) => {
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<git2::Repository> {
|
|||
// 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 <green>{}</>.",
|
||||
config.1.local.display()
|
||||
);
|
||||
let repo = Repository::init(&expanded)?;
|
||||
fs::File::create(sentinel)?;
|
||||
Ok(repo)
|
||||
|
|
|
@ -45,7 +45,7 @@ pub fn run_init(candidates: Vec<ResPathBuf>) -> Result<(), Box<dyn Error>> {
|
|||
// 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(())
|
||||
}
|
||||
|
||||
|
|
16
src/main.rs
16
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<dyn Error>> {
|
|||
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(())
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue