use chrono::{DateTime, Local};
use clap::{Parser, builder::TypedValueParser};
use miette::Result;
use regex::Regex;
use adnv::{Config, ops::check};
#[allow(clippy::needless_pass_by_value)]
pub fn parse_datetime(value: String) -> Result<DateTime<Local>, String> {
use chrono::NaiveDate;
if let Ok(datetime) = value.parse::<DateTime<Local>>() {
Ok(datetime)
} else {
let date = value
.parse::<NaiveDate>()
.map_err(|err| format!("valid RFC3339-formatted date or datetime: {err}"))?;
Ok(date
.and_hms_opt(0, 0, 0)
.unwrap()
.and_local_timezone(Local)
.unwrap())
}
}
#[derive(Debug, Parser)]
pub struct Command {
#[arg(
short,
long,
env = "ADNV_CHECK_LAST",
conflicts_with = "since",
help_heading = "Filtering options"
)]
last: Option<humantime::Duration>,
#[arg(
short = 'S',
long,
env = "ADNV_CHECK_SINCE",
conflicts_with = "last",
value_parser = clap::builder::StringValueParser::new().try_map(parse_datetime),
help_heading = "Filtering options"
)]
since: Option<DateTime<Local>>,
#[arg(
short,
long = "output",
env = "ADNV_CHECK_OUTPUTS",
value_name = "OUTPUT_NAME",
value_delimiter = ','
)]
outputs: Vec<String>,
#[arg(short, long, env = "ADNV_CHECK_INCLUDE", value_name = "INCLUDE_REGEX")]
include: Option<Regex>,
#[arg(short, long, env = "ADNV_CHECK_EXCLUDE", value_name = "EXCLUDE_REGEX")]
exclude: Option<Regex>,
sources: Vec<check::Source>,
}
impl Command {
pub async fn run(self, config: Option<&Config>) -> Result<()> {
let sources = match self.sources.as_slice() {
[] => config.map_or(&[][..], |config| config.check.sources.as_slice()),
sources => {
if config.is_some() {
tracing::warn!("Configuration file has not been read");
}
sources
}
};
let outputs = config
.map(|config| config.check.outputs.clone())
.unwrap_or_default();
adnv::ops::check::run(
check::Options {
last: self.last.map(Into::into),
since: self.since,
outputs: self.outputs,
include: self.include,
exclude: self.exclude,
},
sources,
outputs,
)
.await?;
Ok(())
}
}