use crate::Result;
use crate::expr::Expression;
use camino::{Utf8Path, Utf8PathBuf};
use core::time::Duration;
use ohno::IntoAppError;
use serde::{Deserialize, Serialize};
use std::fs;
use std::io;
pub const DEFAULT_CONFIG_TOML: &str = include_str!("../../default_config.toml");
#[derive(Debug, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct Config {
#[serde(default)]
pub deny_if_any: Vec<Expression>,
#[serde(default)]
pub accept_if_any: Vec<Expression>,
#[serde(default)]
pub accept_if_all: Vec<Expression>,
#[serde(default = "default_crates_cache_ttl", with = "humantime_serde")]
pub crates_cache_ttl: Duration,
#[serde(default = "default_hosting_cache_ttl", with = "humantime_serde")]
pub hosting_cache_ttl: Duration,
#[serde(default = "default_codebase_cache_ttl", with = "humantime_serde")]
pub codebase_cache_ttl: Duration,
#[serde(default = "default_coverage_cache_ttl", with = "humantime_serde")]
pub coverage_cache_ttl: Duration,
#[serde(default = "default_advisories_cache_ttl", with = "humantime_serde")]
pub advisories_cache_ttl: Duration,
}
const fn default_crates_cache_ttl() -> Duration {
Duration::from_hours(24 * 7)
}
const fn default_hosting_cache_ttl() -> Duration {
Duration::from_hours(24 * 7)
}
const fn default_codebase_cache_ttl() -> Duration {
Duration::from_hours(24 * 7)
}
const fn default_coverage_cache_ttl() -> Duration {
Duration::from_hours(24 * 7)
}
const fn default_advisories_cache_ttl() -> Duration {
Duration::from_hours(24 * 7)
}
impl Config {
pub fn load(workspace_root: &Utf8Path, config_path: Option<&Utf8PathBuf>) -> Result<Self> {
let (final_path, text) = if let Some(path) = config_path {
let text = fs::read_to_string(path).into_app_err_with(|| format!("reading cargo-aprz configuration from {path}"))?;
(path.clone(), text)
} else {
let path = workspace_root.join("aprz.toml");
match fs::read_to_string(&path) {
Ok(text) => (path, text),
Err(e) if e.kind() == io::ErrorKind::NotFound => {
return Ok(Self::default());
}
Err(e) => return Err(e).into_app_err_with(|| format!("reading cargo-aprz configuration from {path}")),
}
};
let config: Self = toml::from_str(&text).into_app_err_with(|| format!("parsing configuration from {final_path}"))?;
Ok(config)
}
pub fn save_default(output_path: &Utf8Path) -> Result<()> {
fs::write(output_path, DEFAULT_CONFIG_TOML).into_app_err_with(|| format!("writing default configuration to {output_path}"))?;
Ok(())
}
}
impl Default for Config {
fn default() -> Self {
toml::from_str(DEFAULT_CONFIG_TOML).expect("default_config.toml should be valid TOML that deserializes to Config")
}
}