use super::daemon_utils::daemon_base_url;
use super::reindex_engine::{
register_index_with_daemon, register_index_with_daemon_filtered, run_reindex,
run_reindex_force, RegisterFilters,
};
use crate::core::repo_config::{language_to_exts, IndexConfig, RepoConfig, CONFIG_FILENAME};
use anyhow::Result;
use colored::Colorize;
pub async fn handle_index(
path: Option<std::path::PathBuf>,
name: Option<String>,
force: bool,
timeout_secs: u64,
) -> Result<()> {
let cwd = std::env::current_dir().unwrap_or_default();
let project_path = path.unwrap_or(cwd);
crate::commands::daemon_guard::ensure_daemon_running_or_exit(&daemon_base_url()).await?;
match RepoConfig::load(&project_path) {
Ok(Some(cfg)) => {
println!(
"{} loaded {} ({} index{} declared)",
"→".cyan(),
CONFIG_FILENAME.bold(),
cfg.indexes.len(),
if cfg.indexes.len() == 1 { "" } else { "es" },
);
if name.is_some() {
eprintln!(
"{} --name is ignored when {} is present",
"ℹ".yellow(),
CONFIG_FILENAME
);
}
for idx in &cfg.indexes {
let filters = filters_from_index_config(idx);
index_one_with_filters(&idx.name, &project_path, force, timeout_secs, &filters)
.await?;
}
return Ok(());
}
Ok(None) => {
}
Err(e) => {
anyhow::bail!("could not parse {}: {e}", CONFIG_FILENAME);
}
}
let index_name = name.unwrap_or_else(|| {
project_path
.file_name()
.unwrap_or_default()
.to_string_lossy()
.into_owned()
});
index_one(&index_name, &project_path, force, timeout_secs).await
}
pub(crate) fn filters_from_index_config(idx: &IndexConfig) -> RegisterFilters {
let mut extensions: Vec<String> = Vec::new();
for lang in &idx.languages {
for e in language_to_exts(lang) {
extensions.push((*e).to_string());
}
}
extensions.sort();
extensions.dedup();
RegisterFilters {
include_paths: idx.paths.clone(),
exclude_globs: idx.exclude.clone(),
extensions,
domain_terms: idx.domain_terms.clone(),
}
}
async fn index_one(
index_name: &str,
project_path: &std::path::Path,
force: bool,
timeout_secs: u64,
) -> Result<()> {
index_one_with_filters(
index_name,
project_path,
force,
timeout_secs,
&RegisterFilters::default(),
)
.await
}
async fn index_one_with_filters(
index_name: &str,
project_path: &std::path::Path,
force: bool,
timeout_secs: u64,
filters: &RegisterFilters,
) -> Result<()> {
let result = if filters.include_paths.is_empty()
&& filters.exclude_globs.is_empty()
&& filters.extensions.is_empty()
&& filters.domain_terms.is_empty()
{
register_index_with_daemon(index_name, project_path).await
} else {
register_index_with_daemon_filtered(index_name, project_path, filters).await
};
let (created, daemon_reachable) = result?;
if !daemon_reachable {
anyhow::bail!(
"Daemon not reachable at {}. Start it with `trusty-search start`.",
daemon_base_url(),
);
}
if created {
println!(
"{} '{}' registered at {}",
"✓".green(),
index_name.bold(),
project_path.display()
);
}
if force {
run_reindex_force(index_name, project_path, timeout_secs).await?;
} else {
run_reindex(index_name, project_path, timeout_secs).await?;
}
Ok(())
}