mod checks;
use std::collections::HashMap;
use super::database::RepositoryIndex;
use crate::index::traits::GraphStore;
use crate::model::document::{
CheckResult, CheckStatus, ValidationIssue, ValidationReport, ValidationSummary,
};
const CHECKS: &[&str] = &[
"broken_links",
"scan_errors",
"missing_index_files",
"unsupported_encoding",
"oversized_frontmatter",
"invalid_yaml",
"missing_type",
"duplicate_concept",
"duplicate_content",
"circular_references",
"reserved_file_frontmatter",
];
impl RepositoryIndex {
pub fn validate(&self) -> Result<Vec<ValidationIssue>, anyhow::Error> {
Ok(self.validate_report()?.issues)
}
pub fn validate_report(&self) -> Result<ValidationReport, anyhow::Error> {
let mut issues = Vec::new();
if let Some(ref gs) = self.graph_store {
issues.extend(gs.validate_links()?);
}
issues.extend(self.check_missing_index_files());
issues.extend(self.validate_files());
if let Some(ref gs) = self.graph_store {
issues.extend(gs.detect_circular_references()?);
}
Ok(self.build_report(issues))
}
#[allow(dead_code)]
pub fn validate_incremental(
&self,
previous_hashes: Option<&HashMap<String, String>>,
) -> Result<ValidationReport, anyhow::Error> {
let mut issues = Vec::new();
if let Some(ref gs) = self.graph_store {
issues.extend(gs.validate_links()?);
issues.extend(gs.detect_circular_references()?);
}
issues.extend(self.check_missing_index_files());
issues.extend(self.validate_files_changed(previous_hashes));
Ok(self.build_report(issues))
}
fn build_report(&self, issues: Vec<ValidationIssue>) -> ValidationReport {
let total = issues.len();
let errors = issues.iter().filter(|i| i.severity == "error").count();
let warnings = issues.iter().filter(|i| i.severity == "warning").count();
let infos = issues.iter().filter(|i| i.severity == "info").count();
let checks: Vec<CheckResult> = CHECKS
.iter()
.map(|name| {
let count = issues
.iter()
.filter(|i| i.category.as_str() == *name)
.count();
CheckResult {
check_name: name.to_string(),
status: if count == 0 {
CheckStatus::Pass
} else if *name == "broken_links"
|| *name == "missing_index_files"
|| *name == "reserved_file_frontmatter"
|| *name == "circular_references"
{
CheckStatus::Warn
} else {
CheckStatus::Fail
},
issue_count: count,
}
})
.collect();
ValidationReport {
summary: ValidationSummary {
total_issues: total,
errors,
warnings,
infos,
checks,
},
issues,
}
}
}