use anyhow::Result;
use std::path::Path;
use tracing::{debug, info};
use crate::git::{self, EnrichmentStats, GitHistory};
use crate::graph::GraphStore;
pub struct Pipeline {
graph: GraphStore,
enable_git_enrichment: bool,
repo_id: Option<String>,
}
impl Pipeline {
pub fn new(graph: GraphStore) -> Self {
Self {
graph,
enable_git_enrichment: true,
repo_id: None,
}
}
pub fn without_git(mut self) -> Self {
self.enable_git_enrichment = false;
self
}
pub fn with_repo_id(mut self, repo_id: impl Into<String>) -> Self {
self.repo_id = Some(repo_id.into());
self
}
pub fn ingest(&self, repo_path: &Path) -> Result<IngestStats> {
let mut stats = IngestStats::default();
if self.enable_git_enrichment {
match self.enrich_with_git(repo_path) {
Ok(git_stats) => {
stats.git_enrichment = Some(git_stats);
}
Err(e) => {
debug!("Git enrichment skipped or failed: {}", e);
}
}
}
Ok(stats)
}
fn enrich_with_git(&self, repo_path: &Path) -> Result<EnrichmentStats> {
git::enrichment::enrich_graph_with_git(
repo_path,
&self.graph,
self.repo_id.as_deref(),
)
}
pub fn enrich_git_only(&self, repo_path: &Path) -> Result<EnrichmentStats> {
self.enrich_with_git(repo_path)
}
pub fn graph(&self) -> &GraphStore {
&self.graph
}
}
#[derive(Default, Debug)]
pub struct IngestStats {
pub files: usize,
pub functions: usize,
pub classes: usize,
pub edges: usize,
pub git_enrichment: Option<EnrichmentStats>,
}
impl IngestStats {
pub fn has_git_enrichment(&self) -> bool {
self.git_enrichment.is_some()
}
pub fn summary(&self) -> String {
let mut parts = vec![
format!("{} files", self.files),
format!("{} functions", self.functions),
format!("{} classes", self.classes),
format!("{} edges", self.edges),
];
if let Some(ref git) = self.git_enrichment {
parts.push(format!(
"git: {} funcs, {} classes, {} commits",
git.functions_enriched, git.classes_enriched, git.commits_created
));
}
parts.join(", ")
}
}
#[cfg(test)]
mod tests {
use super::*;
use tempfile::tempdir;
#[test]
fn test_pipeline_creation() -> Result<()> {
let dir = tempdir()?;
let graph_path = dir.path().join("graph");
let graph = GraphStore::new(&graph_path)?;
let pipeline = Pipeline::new(graph)
.without_git()
.with_repo_id("test-repo");
assert!(!pipeline.enable_git_enrichment);
assert_eq!(pipeline.repo_id, Some("test-repo".to_string()));
Ok(())
}
#[test]
fn test_ingest_stats_summary() {
let mut stats = IngestStats {
files: 10,
functions: 50,
classes: 5,
edges: 100,
git_enrichment: None,
};
assert!(!stats.has_git_enrichment());
assert!(stats.summary().contains("10 files"));
stats.git_enrichment = Some(EnrichmentStats {
functions_enriched: 45,
classes_enriched: 5,
commits_created: 20,
edges_created: 50,
files_skipped: 2,
cache_hits: 0,
cache_misses: 0,
});
assert!(stats.has_git_enrichment());
assert!(stats.summary().contains("git:"));
}
}