use std::path::Path;
use anyhow::{Context, Result};
use rusqlite::Connection;
use crate::db;
use crate::model::CoverageData;
use crate::parsers::{self, Format};
pub fn normalize_paths(data: &mut CoverageData, root: &Path) {
for file in &mut data.files {
let path = Path::new(&file.path);
if path.is_absolute() && path.starts_with(root) {
if let Ok(relative) = path.strip_prefix(root) {
file.path = relative.to_string_lossy().into_owned();
}
}
}
}
pub fn ingest(
conn: &mut Connection,
file_path: &Path,
format_override: Option<&str>,
report_name: Option<&str>,
overwrite: bool,
root: Option<&Path>,
) -> Result<(i64, Format, String)> {
let content = std::fs::read(file_path)
.with_context(|| format!("Failed to read {}", file_path.display()))?;
let parser = if let Some(fmt_str) = format_override {
let format = fmt_str.parse::<Format>()?;
parsers::for_format(format)
} else {
parsers::detect(file_path, &content)
.ok_or_else(|| anyhow::anyhow!("Unknown coverage format"))?
};
let format = parser.format();
let mut data = parser.parse(&content)?;
if let Some(root) = root {
normalize_paths(&mut data, root);
}
if data.files.is_empty() {
eprintln!(
"Warning: coverage file '{}' contains no source files",
file_path.display()
);
}
let name = match report_name {
Some(n) => n.to_string(),
None => file_path
.file_name()
.and_then(|n| n.to_str())
.unwrap_or("unnamed")
.to_string(),
};
let source_file_str = file_path.to_str();
let report_id = db::insert_coverage(
conn,
&name,
&format.to_string(),
source_file_str,
&data,
overwrite,
)?;
Ok((report_id, format, name))
}