#![allow(dead_code)] pub const BUFFER_SIZE: usize = 4096; #[macro_use] mod log; mod bytes; mod ext; pub use ext::*; mod error; mod hash; mod container; mod config; mod arg; mod proc; #[cfg(test)] mod test { use super::*; use std::{ path::Path, }; #[test] pub fn args() -> Result<(), arg::Error> { macro_rules! string_literal { ($($strings:expr),*) => { vec![$( format!($strings), )*] } } let args = string_literal!["-lsd", "--load-file", "hello", "--load-save", "load-save!", "--", "test-input", "test-input", "test-input-3", "test-input-2"]; println!("{:?}", arg::parse(args)?); Ok(()) } #[test] pub fn test() -> Result<(), error::Error> { let mut cont = container::DupeMap::new(); let mode = config::Mode::default(); let path = Path::new("test-input"); assert_eq!(proc::DupeCount{total:4, dupes:2}, proc::do_dir(path, 0, &mut cont, &mode)?); Ok(()) } #[cfg(feature="threads")] pub async fn _test_async() -> Result<(), error::Error> { use std::sync::Arc; use tokio::{ sync::Mutex, }; let cont = Arc::new(Mutex::new(container::DupeMap::new())); let mode = config::Mode::default(); let path = Path::new("test-input"); assert_eq!(proc::DupeCount{total:4, dupes:2}, proc::do_dir_async(path, 0, cont, mode).await?); Ok(()) } #[cfg(feature="threads")] #[test] pub fn test_async() -> Result<(), error::Error> { tokio_test::block_on(_test_async()) } } fn parse_args() -> Result { match arg::parse_args()? { arg::Output::Normal(conf) => Ok(conf), _ => arg::usage(), } } #[cfg_attr(feature="threads", tokio::main)] #[cfg(feature="threads")] async fn main() -> Result<(), Box> { use tokio::{ fs::{ OpenOptions, }, sync, }; use std::{ path::Path, }; let args = parse_args().into_string()?; let lmode = &args.mode.logging_mode; log!(Debug, lmode => "Args parsed: {:?}", args); let mut children = Vec::new(); let mut hashes = container::DupeMap::new(); // Load hashes for load in args.load.iter() { let load = Path::new(load); if load.exists() { if load.is_file() { if let Some(mut file) = OpenOptions::new() .read(true) .open(load).await.log_and_forget(lmode, log::Level::Warning) { } } else { log!(Warning, lmode => "Exclusing directory from load path {:?}", load); } } else { log!(Info, lmode => "Ignoring non-existant load path {:?}", load); } } for path in args.paths.iter() { let path = Path::new(path); if path.is_dir() { children.push(tokio::task::spawn(async move { //proc::do_dir_async() })); } } Ok(()) } #[cfg(not(feature="threads"))] fn main() -> Result<(), error::Error> { let args = parse_args()?; log!(Fatal, log::Mode::Error => "{:?}", args); Ok(()) }