use std::path::{Path, PathBuf};
use crate::error::{Result, SearchError};
#[derive(Debug, Clone)]
pub struct IndexConfig {
pub root: PathBuf,
pub docstore_path: PathBuf,
pub metadata_path: PathBuf,
pub segments_dir: PathBuf,
pub lock_path: PathBuf,
}
impl IndexConfig {
pub fn new(root: PathBuf) -> Self {
IndexConfig {
docstore_path: root.join("docstore.redb"),
metadata_path: root.join("metadata.redb"),
segments_dir: root.join("segments"),
lock_path: root.join("write.lock"),
root,
}
}
pub fn segment_dir(&self, id: u32) -> PathBuf {
self.segments_dir.join(format!("{:04}", id))
}
pub fn ensure_dirs(&self) -> Result<()> {
std::fs::create_dir_all(&self.root)?;
std::fs::create_dir_all(&self.segments_dir)?;
Ok(())
}
}
pub fn resolve_index(hint: Option<PathBuf>) -> Result<IndexConfig> {
if let Some(path) = hint {
return Ok(IndexConfig::new(path));
}
if let Ok(cwd) = std::env::current_dir() {
let mut dir: &Path = &cwd;
loop {
let candidate = dir.join(".searchindex");
if candidate.exists() {
return Ok(IndexConfig::new(candidate));
}
match dir.parent() {
Some(parent) => dir = parent,
None => break,
}
}
}
let home = home_dir().ok_or_else(|| {
SearchError::IndexNotFound(PathBuf::from("~/.searchindex"))
})?;
Ok(IndexConfig::new(home.join(".searchindex")))
}
pub fn require_index(hint: Option<PathBuf>) -> Result<IndexConfig> {
let config = resolve_index(hint)?;
if !config.root.exists() {
return Err(SearchError::IndexNotFound(config.root));
}
Ok(config)
}
fn home_dir() -> Option<PathBuf> {
std::env::var_os("HOME").map(PathBuf::from)
}