diff --git a/Cargo.lock b/Cargo.lock index 38382c4..75f5bf9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13,6 +13,15 @@ dependencies = [ "version_check", ] +[[package]] +name = "aho-corasick" +version = "0.7.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" +dependencies = [ + "memchr", +] + [[package]] name = "anyhow" version = "1.0.62" @@ -47,6 +56,17 @@ dependencies = [ "wildmatch", ] +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi", + "libc", + "winapi", +] + [[package]] name = "autocfg" version = "1.1.0" @@ -213,6 +233,19 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0688c2a7f92e427f44895cd63841bff7b29f8d7a1648b9e7e07a4a365b2e1257" +[[package]] +name = "env_logger" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b2cf0344971ee6c64c31be0d530793fba457d322dfec2810c453d0ef228f9c3" +dependencies = [ + "atty", + "humantime", + "log", + "regex", + "termcolor", +] + [[package]] name = "filetime" version = "0.2.17" @@ -281,10 +314,13 @@ dependencies = [ ] [[package]] -name = "heck" -version = "0.4.0" +name = "hermit-abi" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] [[package]] name = "hex" @@ -312,6 +348,12 @@ dependencies = [ "itoa", ] +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + [[package]] name = "idna" version = "0.2.3" @@ -399,12 +441,6 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "maplit" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" - [[package]] name = "matches" version = "0.1.9" @@ -576,6 +612,23 @@ dependencies = [ "thiserror", ] +[[package]] +name = "regex" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.6.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244" + [[package]] name = "ring" version = "0.16.20" @@ -598,11 +651,12 @@ dependencies = [ "anyhow", "config", "dirs", + "env_logger", "lazy_static", + "log", "notify", "online", "rust-s3", - "spinners", ] [[package]] @@ -656,12 +710,6 @@ dependencies = [ "webpki", ] -[[package]] -name = "rustversion" -version = "1.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97477e48b4cf8603ad5f7aaf897467cf42ab4218a38ef76fb14c2d6773a6d6a8" - [[package]] name = "rxml" version = "0.8.1" @@ -775,45 +823,12 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" -[[package]] -name = "spinners" -version = "4.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08615eea740067d9899969bc2891c68a19c315cb1f66640af9a9ecb91b13bcab" -dependencies = [ - "lazy_static", - "maplit", - "strum", -] - [[package]] name = "static_assertions" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" -[[package]] -name = "strum" -version = "0.24.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f" -dependencies = [ - "strum_macros", -] - -[[package]] -name = "strum_macros" -version = "0.24.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "rustversion", - "syn", -] - [[package]] name = "subtle" version = "2.4.1" @@ -831,6 +846,15 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "termcolor" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" +dependencies = [ + "winapi-util", +] + [[package]] name = "thiserror" version = "1.0.32" diff --git a/Cargo.toml b/Cargo.toml index 03f49c7..4b27571 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,5 +11,6 @@ dirs = "4.0.0" lazy_static = "1.4.0" notify = "5.0.0" rust-s3 = { version = "0.32.3", default-features = false, features = ["sync", "tags", "sync-rustls-tls"] } -spinners = "4.1.0" -online = { version = "3.0.1", default-features = false, features = ["sync"] } \ No newline at end of file +online = { version = "3.0.1", default-features = false, features = ["sync"] } +log = "0.4.17" +env_logger = "0.9.0" diff --git a/config.example.toml b/config.example.toml index 8ba2a2a..ed285e3 100644 --- a/config.example.toml +++ b/config.example.toml @@ -2,6 +2,7 @@ provider = "s3" interval = 600000 path = "/home/abdulrahman/Sync" +log = "info" [s3] bucket_name = "sync" diff --git a/src/cloud/adapter.rs b/src/cloud/adapter.rs index 6b0977f..3611176 100644 --- a/src/cloud/adapter.rs +++ b/src/cloud/adapter.rs @@ -12,4 +12,6 @@ pub trait CloudAdapter { fn read_file(path: &Path) -> Result> { Ok(std::fs::read(path)?) } + + fn kind(&self) -> &'static str; } diff --git a/src/cloud/adapters/s3.rs b/src/cloud/adapters/s3.rs index e18ae57..1bf2a75 100644 --- a/src/cloud/adapters/s3.rs +++ b/src/cloud/adapters/s3.rs @@ -101,4 +101,8 @@ impl CloudAdapter for Cloud { self.delete(oldpath)?; Ok(()) } + + fn kind(&self) -> &'static str { + "s3" + } } diff --git a/src/main.rs b/src/main.rs index 1ab6eb3..81a6320 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,11 +7,13 @@ mod util; use cloud::{adapters::*, CloudAdapter}; use config::Config; +use log::LevelFilter; use notify::{event::*, recommended_watcher, RecursiveMode, Watcher}; use std::{ collections::HashSet, path::PathBuf, process::exit, + str::FromStr, sync::{mpsc::channel, Arc, Mutex}, thread, time::Duration, @@ -36,6 +38,16 @@ lazy_static! { } fn main() -> Result<()> { + let log_level = SETTINGS + .get_string("main.log") + .unwrap_or_else(|_| "debug".to_owned()) + .to_uppercase(); + + env_logger::builder() + .format_timestamp(None) + .filter_level(LevelFilter::from_str(&log_level).expect("Invalid log level format")) + .init(); + let cloud_ref = Arc::new( match SETTINGS .get_string("main.provider") @@ -52,7 +64,7 @@ fn main() -> Result<()> { // "onedrive" => onedrive::Cloud::new(), // "protondrive" => protondrive::Cloud::new(), x => { - println!("Unspported cloud provider: {}", x); + log::error!("Unsupported cloud provider: {}", x); exit(1); } }, @@ -62,18 +74,27 @@ fn main() -> Result<()> { .get("main.interval") .expect("Missing/Invalid interval value"); - let cloud = cloud_ref.clone(); + log::info!("Selected cloud provider: {}", cloud_ref.kind()); + log::info!("Syncing directory: {}", SYNC_DIR.to_str().unwrap()); + log::info!("Syncing delay: {interval:?}ms"); + let cloud = cloud_ref.clone(); let online_task = thread::spawn(move || loop { check_connectivity(); if *IS_INTERNET_AVAILABLE.lock().unwrap() { *SYNCING.lock().unwrap() = true; - spinner("Syncing...", "Synced!", || cloud.sync().map(|_| {})); + + maybe_error( + cloud + .sync() + .map(|count| log::debug!("{count:?} file has synced")), + ); + *SYNCING.lock().unwrap() = false; thread::sleep(Duration::from_millis(interval)); } else { - println!("Skip syncing.. there are no internet connection"); + log::warn!("Skip syncing.. there are no internet connection"); } }); @@ -89,39 +110,33 @@ fn main() -> Result<()> { let event = match event { Ok(e) => e, Err(err) => { - println!("Notify Error: {:?}", err); + log::error!("Notify Error: {:?}", err); continue; } }; - println!("{:?}", event); + log::debug!("{:?}", event); if !*IS_INTERNET_AVAILABLE.lock().unwrap() { - println!("Skip local syncing.. there are no internet connection"); + log::warn!("Skip local syncing.. there are no internet connection"); continue; } if *SYNCING.lock().unwrap() { - println!("Ignore event since online syncing is working"); + log::debug!("Ignore event since online syncing is working"); continue; } match event.kind { EventKind::Create(CreateKind::File) => { - spinner("Saveing file...", "File saved", || { - cloud.save(&event.paths[0]) - }); + maybe_error(cloud.save(&event.paths[0])); } EventKind::Remove(RemoveKind::File | RemoveKind::Folder) => { - spinner("Deleteing file...", "File deleted", || { - cloud.delete(&event.paths[0]) - }); + maybe_error(cloud.delete(&event.paths[0])); } EventKind::Access(AccessKind::Close(AccessMode::Write)) => { if changes.remove(&event.paths[0]) { - spinner("Changeing file...", "File changed", || { - cloud.save(&event.paths[0]) - }); + maybe_error(cloud.save(&event.paths[0])); } } EventKind::Modify(kind) => match kind { @@ -130,9 +145,7 @@ fn main() -> Result<()> { } ModifyKind::Name(_) => { if event.paths.len() == 2 { - spinner("Renaming file...", "File renamed", || { - cloud.rename(&event.paths[0], &event.paths[1]) - }); + maybe_error(cloud.rename(&event.paths[0], &event.paths[1])); } } _ => {} diff --git a/src/util.rs b/src/util.rs index 07a0fea..92520f7 100644 --- a/src/util.rs +++ b/src/util.rs @@ -1,6 +1,5 @@ use crate::{IS_INTERNET_AVAILABLE, SYNC_DIR}; pub use anyhow::Result; -use spinners::{Spinner, Spinners}; use std::{ fs::{self, DirEntry}, io, @@ -55,22 +54,6 @@ pub fn walk_dir(dir: PathBuf) -> io::Result> { Ok(result) } -pub fn spinner(message: &str, stop_message: &str, operation: F) -where - F: Fn() -> Result<()>, -{ - let mut sp = Spinner::new(Spinners::Dots9, message.into()); - - if let Err(err) = operation() { - sp.stop(); - println!("An error has occurred: {err:?}"); - } else if stop_message.is_empty() { - sp.stop(); - } else { - sp.stop_with_message(stop_message.into()); - } -} - pub fn settings_file_path() -> Result { let mut path = dirs::config_dir().unwrap(); @@ -99,3 +82,9 @@ pub fn settings_file_path() -> Result { pub fn check_connectivity() { *IS_INTERNET_AVAILABLE.lock().unwrap() = online::sync::check(None).is_ok(); } + +pub fn maybe_error(result: Result<()>) { + if let Err(error) = result { + log::error!("An error has occurred: {error:?}"); + } +}