use super::MaintenanceTask;
use crate::Config;
use crate::config::InvalidValue;
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[non_exhaustive]
pub enum MaintenanceStrategy {
Incremental,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[non_exhaustive]
pub enum AutoThreshold {
Disabled,
Always,
Count(u32),
}
#[derive(Debug, thiserror::Error)]
#[error("invalid maintenance configuration for task '{task}'")]
#[non_exhaustive]
pub struct TaskConfigError {
pub task: MaintenanceTask,
#[source]
pub source: InvalidValue,
}
#[derive(Clone, Copy, Debug)]
pub struct MaintenanceConfig<'a> {
config: &'a Config,
}
impl<'a> MaintenanceConfig<'a> {
pub fn new(config: &'a Config) -> Self {
Self { config }
}
pub fn command_auto(&self) -> Result<bool, InvalidValue> {
if let Some(enabled) = self.config.boolean("maintenance", None, "auto")? {
return Ok(enabled);
}
let value = self.config.integer("gc", None, "auto")?.unwrap_or(6700);
let value = i32::try_from(value).map_err(|_| {
InvalidValue::new(
"gc",
"auto",
self.config.value("gc", None, "auto").flatten(),
)
})?;
Ok(value > 0)
}
pub fn strategy(&self) -> Result<Option<MaintenanceStrategy>, InvalidValue> {
match self.config.value("maintenance", None, "strategy") {
None => Ok(None),
Some(Some(b"incremental")) => Ok(Some(MaintenanceStrategy::Incremental)),
Some(value) => Err(InvalidValue::new("maintenance", "strategy", value)),
}
}
pub fn task_enabled(&self, task: MaintenanceTask) -> Result<Option<bool>, TaskConfigError> {
self.config
.boolean("maintenance", Some(task.to_string().as_bytes()), "enabled")
.map_err(|source| TaskConfigError { task, source })
}
pub fn auto_threshold(
&self,
task: MaintenanceTask,
) -> Result<Option<AutoThreshold>, TaskConfigError> {
let default = match task {
MaintenanceTask::CommitGraph | MaintenanceTask::LooseObjects => 100,
MaintenanceTask::IncrementalRepack => 10,
MaintenanceTask::Gc | MaintenanceTask::Prefetch | MaintenanceTask::PackRefs => {
return Ok(None);
}
};
let name = task.to_string();
let subsection = Some(name.as_bytes());
let invalid = |source| TaskConfigError { task, source };
let value = self
.config
.integer("maintenance", subsection, "auto")
.map_err(invalid)?
.unwrap_or(default);
let value = i32::try_from(value).map_err(|_| {
invalid(InvalidValue::new(
"maintenance",
"auto",
self.config
.value("maintenance", subsection, "auto")
.flatten(),
))
})?;
Ok(Some(match value {
0 => AutoThreshold::Disabled,
value if value < 0 => AutoThreshold::Always,
value => AutoThreshold::Count(value as u32),
}))
}
}