use std::path::Path;
use std::sync::mpsc::Sender;
use std::sync::{Arc, Mutex};
use anyhow::{Context, Result};
use tracing::info;
use crate::mount::handler::{flush_mount_to_disk, on_project_discovery};
use crate::mount::{MountTable, MountedEvent};
use crate::server::db::SearchDb;
pub type BuildResult = (Arc<Mutex<MountTable>>, Arc<Mutex<SearchDb>>);
pub fn build_index_to_db(
path: &Path,
enable_fts: bool,
load_from_cache: bool,
tx: Option<Sender<MountedEvent>>,
) -> Result<BuildResult> {
let root = path
.canonicalize()
.with_context(|| format!("cannot resolve path: {}", path.display()))?;
info!("building index at {}", root.display());
let mount_table = Arc::new(Mutex::new(MountTable::new(root.clone())));
let db = Arc::new(Mutex::new(if enable_fts {
SearchDb::new().context("failed to create search database")?
} else {
SearchDb::new_no_fts().context("failed to create search database")?
}));
on_project_discovery(&root, &mount_table, &db, load_from_cache, tx)
.context("failed to process root project")?;
Ok((mount_table, db))
}
pub fn build_index(path: &Path) -> Result<()> {
let (mount_table, db) = build_index_to_db(path, false, false, None)?;
let mt = mount_table
.lock()
.map_err(|e| anyhow::anyhow!("mount table lock poisoned: {e}"))?;
let mut total_files = 0usize;
let mut total_symbols = 0usize;
let mut total_texts = 0usize;
for (root, mount) in mt.iter() {
if mount.dirty {
flush_mount_to_disk(root, &mt, &db)
.with_context(|| format!("failed to flush index to disk for {}", root.display()))?;
let project_str = mt.relative_project(root);
let db_guard = db
.lock()
.map_err(|e| anyhow::anyhow!("db lock poisoned: {e}"))?;
let (files, symbols, texts, _refs) = db_guard.export_for_project(&project_str)?;
drop(db_guard);
let name = root
.file_name()
.and_then(|n| n.to_str())
.unwrap_or("unknown");
info!(
"wrote .codeindex/ for '{}': {} files, {} symbols, {} texts",
name,
files.len(),
symbols.len(),
texts.len()
);
total_files += files.len();
total_symbols += symbols.len();
total_texts += texts.len();
}
}
info!(
"total: {} files, {} symbols, {} texts",
total_files, total_symbols, total_texts
);
Ok(())
}
pub fn run(path: &Path) -> Result<()> {
build_index(path)
}