use std::path::Path;
use std::sync::Arc;
use std::sync::mpsc;
use anyhow::{Context, Result};
use crate::cli::build::build_index_to_db;
use crate::mount::MountedEvent;
use crate::mount::handler::{flush_mount_to_disk, run_event_loop};
use crate::server::mcp::start_server;
pub fn run(path: &Path, watch: bool) -> Result<()> {
let _root = path
.canonicalize()
.with_context(|| format!("cannot resolve path: {}", path.display()))?;
let (tx, rx): (
Option<mpsc::Sender<MountedEvent>>,
Option<mpsc::Receiver<MountedEvent>>,
) = if watch {
tracing::info!("starting watch mode");
let (tx, rx) = mpsc::channel();
(Some(tx), Some(rx))
} else {
(None, None)
};
let (mount_table, db) =
build_index_to_db(path, true, true, tx.clone()).context("failed to build/load index")?;
{
let mt = mount_table
.lock()
.map_err(|e| anyhow::anyhow!("mount table lock poisoned: {e}"))?;
for (mount_root, mount) in mt.iter() {
if mount.dirty {
flush_mount_to_disk(mount_root, &mt, &db)
.with_context(|| format!("failed to flush {}", mount_root.display()))?;
}
}
}
if let (Some(tx), Some(rx)) = (tx, rx) {
let mount_table_clone = Arc::clone(&mount_table);
let db_clone = Arc::clone(&db);
std::thread::spawn(move || {
if let Err(e) = run_event_loop(rx, tx, mount_table_clone, db_clone) {
tracing::error!("event loop error: {}", e);
}
});
}
let rt = tokio::runtime::Runtime::new().context("failed to create tokio runtime")?;
rt.block_on(async {
tracing::info!("starting MCP server on stdio");
start_server(db, mount_table).await
})
}