///|
pub(all) struct RuleSet {
format_version : Int
rules : Array[CleanupRule]
} derive(Eq, Debug, ToJson, FromJson)
///|
pub(all) enum RuleConfigIssueKind {
EmptyId
DuplicateId
EmptyTitle
InvalidMinimumSize
InvalidAge
EmptyConditionGroup
} derive(Eq, Debug, ToJson, FromJson)
///|
pub(all) struct RuleConfigIssue {
kind : RuleConfigIssueKind
rule_id : String
message : String
} derive(Eq, Debug, ToJson, FromJson)
///|
fn validate_condition(
condition : RuleCondition,
rule_id : String,
issues : Array[RuleConfigIssue],
) -> Unit {
match condition {
MinimumSize(bytes) =>
if bytes < 0L {
issues.push(RuleConfigIssue::{
kind: InvalidMinimumSize,
rule_id,
message: "MinimumSize must be zero or greater.",
})
}
OlderThan(seconds) =>
if seconds < 0L {
issues.push(RuleConfigIssue::{
kind: InvalidAge,
rule_id,
message: "OlderThan must be zero or greater.",
})
}
Any(conditions) | All(conditions) => {
if conditions.is_empty() {
issues.push(RuleConfigIssue::{
kind: EmptyConditionGroup,
rule_id,
message: "Any and All condition groups cannot be empty.",
})
}
for child in conditions {
validate_condition(child, rule_id, issues)
}
}
Not(child) => validate_condition(child, rule_id, issues)
PathPattern(_) | Extension(_) | EmptyDirectory => ()
}
}
///|
pub fn validate_rule_set(rule_set : RuleSet) -> Array[RuleConfigIssue] {
let issues : Array[RuleConfigIssue] = []
let ids : Map[String, Bool] = Map([])
for rule in rule_set.rules {
if rule.id.trim().is_empty() {
issues.push(RuleConfigIssue::{
kind: EmptyId,
rule_id: rule.id,
message: "Every cleanup rule needs a non-empty id.",
})
} else if ids.get(rule.id) is Some(_) {
issues.push(RuleConfigIssue::{
kind: DuplicateId,
rule_id: rule.id,
message: "Cleanup rule ids must be unique.",
})
} else {
ids[rule.id] = true
}
if rule.title.trim().is_empty() {
issues.push(RuleConfigIssue::{
kind: EmptyTitle,
rule_id: rule.id,
message: "Every cleanup rule needs a title.",
})
}
validate_condition(rule.condition, rule.id, issues)
}
issues
}
///|
pub fn default_rule_set() -> RuleSet {
RuleSet::{ format_version: 1, rules: builtin_cleanup_rules(), }
}
///|
pub fn rule_set_to_json(rule_set : RuleSet, pretty? : Bool = true) -> String {
let json = ToJson::to_json(rule_set)
if pretty {
json.stringify(indent=2)
} else {
json.stringify()
}
}
///|
pub fn rule_set_from_json(source : String) -> RuleSet raise {
let rule_set : RuleSet = @json.from_json(@json.parse(source))
if rule_set.format_version != 1 {
raise Failure("Unsupported cleanup rule format version")
}
let issues = validate_rule_set(rule_set)
if !issues.is_empty() {
raise Failure(
"Invalid cleanup rules: " + issues[0].rule_id + ": " + issues[0].message,
)
}
rule_set
}
///|
pub async fn write_rule_set(path : String, rule_set : RuleSet) -> Unit {
@fs.write_file(path, rule_set_to_json(rule_set))
}
///|
pub async fn read_rule_set(path : String) -> RuleSet {
rule_set_from_json(@fs.read_file(path).text())
}