git_semantic/index/
builder.rs1use chrono::Utc;
2use tracing::debug;
3
4use crate::embedding::ModelManager;
5use crate::git::CommitInfo;
6
7use super::{IndexEntry, IndexError, SemanticIndex};
8
9pub struct IndexBuilder {
10 entries: Vec<IndexEntry>,
11 model_manager: ModelManager,
12 model_version: String,
13 last_commit: Option<String>,
14 include_diffs: bool,
15 created_at: Option<chrono::DateTime<Utc>>,
16}
17
18impl IndexBuilder {
19 pub fn new(mut model_manager: ModelManager, include_diffs: bool) -> Result<Self, IndexError> {
20 model_manager.init()?;
21 let model_version = model_manager.model_version();
22
23 Ok(Self {
24 entries: Vec::new(),
25 model_manager,
26 model_version,
27 last_commit: None,
28 include_diffs,
29 created_at: None,
30 })
31 }
32
33 pub fn from_existing(
34 index: SemanticIndex,
35 mut model_manager: ModelManager,
36 ) -> Result<Self, IndexError> {
37 model_manager.init()?;
38 let model_version = model_manager.model_version();
39 let include_diffs = index.metadata.include_diffs;
40 let created_at = Some(index.metadata.created_at);
41
42 Ok(Self {
43 entries: index.entries,
44 model_manager,
45 model_version,
46 last_commit: Some(index.last_commit),
47 include_diffs,
48 created_at,
49 })
50 }
51
52 pub fn set_last_commit(&mut self, hash: String) {
54 self.last_commit = Some(hash);
55 }
56
57 pub fn add_commit(&mut self, commit: CommitInfo) -> Result<(), IndexError> {
58 if self.entries.iter().any(|e| e.commit.hash == commit.hash) {
59 debug!("Commit {} already indexed, skipping", &commit.hash[..7]);
60 return Ok(());
61 }
62
63 debug!("Adding commit: {}", &commit.hash[..7]);
64
65 let text = commit.to_text(self.include_diffs);
66 let embedding_array = self.model_manager.encode_text(&text)?;
67 let embedding = embedding_array.to_vec();
68
69 let entry = IndexEntry { commit, embedding };
70 self.entries.push(entry);
71
72 Ok(())
73 }
74
75 pub fn build(self) -> SemanticIndex {
76 let last_commit = self.last_commit.unwrap_or_else(|| "unknown".to_string());
77
78 let mut index = SemanticIndex::new(self.model_version, last_commit, self.include_diffs);
79 index.entries = self.entries;
80 index.metadata.total_commits = index.entries.len();
81 index.metadata.updated_at = Utc::now();
82 if let Some(created_at) = self.created_at {
83 index.metadata.created_at = created_at;
84 }
85
86 index
87 }
88}