//#![allow(unused)] #![allow(incomplete_features)] #![feature(impl_trait_in_bindings)] #![feature(async_closure)] mod config; mod spool; use std::path::PathBuf; use clap::Clap; use tokio::{self, runtime}; use crate::config::*; #[derive(Clap)] #[clap(version = "0.1")] struct Opts { #[clap( name = "config", short = "c", help = "Read this config file by itself, parsed before -C" )] conf: Option, #[clap( name = "configdir", short = "C", help = "Read all config files in this directory" )] conf_dir: Option, #[clap( name = "triggerpath", short = "r", help = "Delete this file to trigger a config reload [NYI]" )] reload_trigger: Option, } fn main() { let opts = Opts::parse(); if opts.reload_trigger.is_some() { println!("Reload trigger file specified, but this option is not supported yet. Ignoring."); } let mut rt = make_runtime(); // Figure out which files we want to configure. let mut confs = Vec::new(); if let Some(main) = opts.conf { confs.push(main.clone()); } if let Some(dir) = opts.conf_dir { match rt.block_on(find_configs(&dir)) { Ok(paths) => confs.extend(paths), Err(e) => { println!("Error reading configuration: {:?}", e); return; } } } // Sanity check. if confs.len() == 0 { println!("No configuration declared, exiting..."); return; } // Process configuration. let config = match rt.block_on(parse_configs(confs)) { Ok(c) => c, Err(e) => { println!("Error parsing configuration: {:?}", e); return; // maybe } }; for s in &config.spool_dirs { if s.send_delay_sec != 0 { println!( "Warning: send delay (as in watch on {:?}) are current not supported, ignoring", s.path ); } } // This is where the real stuff actually happens. match rt.block_on(spool::start_spooling(config)) { Ok(_) => {} Err(e) => println!("fatal error: {:?}", e), } } fn make_runtime() -> runtime::Runtime { runtime::Builder::new() .max_threads(1) .enable_all() .basic_scheduler() .build() .expect("init runtime") }