use ::hm::{
config::{deserialize_file, ensure_config_dir, Config},
do_tasks, hmerror,
};
use chrono::prelude::*;
use indicatif::HumanDuration;
use log::{info, warn};
use simplelog::{ConfigBuilder, LevelFilter, WriteLogger};
use std::{env, fs::File, path::PathBuf, process::exit, string::String, time::Instant};
fn main() {
let args: Vec<String> = env::args().collect();
let mut target_task: Option<String> = None;
let mut arg_config: Option<String> = None;
for i in 0..args.len() {
match args[i].as_str() {
"log" | "logs" => {
println!("{}", recent_log_path());
exit(0)
}
"-t" | "--task" => {
if args.len() > i && !args[i + 1].starts_with('-') {
target_task = Some(args[i + 1].clone());
} else {
hmerror::error(
"-t flag requires specified task immediately after",
"No task was specified.",
);
help();
}
}
"clean" | "--clean" => {
match clean() {
Ok(_) => {
exit(0);
}
Err(e) => {
eprintln!("{}", e);
exit(0);
}
};
}
"-c" | "--config" if args.len() > i + 1 => {
arg_config = Some(args[i + 1].clone());
}
"-h" | "--help" => {
help();
}
_ => {}
}
}
let l = Local::now();
let mut slc = ConfigBuilder::new();
let _ = slc.set_time_offset_to_local();
let mut p = "./logs/".to_string();
let mut log_file_name = String::from("hm-task-");
match std::fs::create_dir("./logs/") {
Ok(_) => {}
Err(e) => {
warn!("Couldn't create log directory :( . Error: {}", e);
}
};
log_file_name.push_str(l.to_string().as_str());
log_file_name.push_str(".log");
p.push_str(log_file_name.as_str());
let _ = WriteLogger::init(LevelFilter::Trace, slc.build(), File::create(p).unwrap());
info!("beginning hm execution...");
let a: Config = match arg_config {
Some(second) => match deserialize_file(&second) {
Ok(c) => c,
Err(e) => {
hmerror::error(
format!("Couldn't open specified config file `{}`", &second).as_str(),
e.to_string().as_str(),
);
exit(1)
}
},
None => {
let _p: PathBuf = ensure_config_dir()
.map_err(|e| {
hmerror::error("Couldn't ensure config dir: {}", e);
exit(1);
})
.unwrap();
match deserialize_file(_p.to_str().unwrap()) {
Ok(c) => c,
Err(e) => {
hmerror::error(
format!(
"Couldn't open assumed (unspecified) config file {}",
_p.to_string_lossy()
)
.as_str(),
e.to_string().as_str(),
);
exit(1)
}
}
}
};
let started = Instant::now();
match do_tasks(Config::as_managed_objects(a), target_task) {
Ok(_) => {
println!("Done in {}.", HumanDuration(started.elapsed()));
exit(0);
}
Err(e) => {
hmerror::error(format!("{}", e).as_str(), "poooooop");
exit(3);
}
}
}
fn recent_log_path() -> String {
let contents: Vec<PathBuf> = std::fs::read_dir("./logs/")
.map(|res| res.map(|e| e.expect("AIYEEEE").path()))
.expect("FURTHER AIYEEE")
.collect::<Vec<_>>();
let mut files: std::collections::BTreeMap<std::time::SystemTime, &PathBuf> =
std::collections::BTreeMap::new();
for item in &contents {
let m = item.metadata();
files.insert(m.unwrap().accessed().unwrap(), item);
}
files
.iter()
.next_back()
.unwrap()
.1
.as_os_str()
.to_string_lossy()
.to_string()
}
fn clean() -> std::io::Result<()> {
std::fs::remove_dir_all("./logs/")?;
Ok(())
}
fn help() {
println!(
"usage:
hm [-h] | [-t|--task] [<task>] | --clean | [-c|--config] [<config>]
-t | --task > run specific named task
-h | --help > this help message
clean > removes the contents of the log directory
log > return the path of the most recent log file (use with your editor - `nvr (hm log)`)
-c | --config [config] > Optional.
if config is not specified, default location of ~/.config/homemaker/config.toml is assumed."
);
exit(0)
}