Skip to main content

omni_index/
cache.rs

1use anyhow::{Context, Result};
2use serde::{Deserialize, Serialize};
3use std::collections::HashMap;
4use std::fs;
5use std::path::{Path, PathBuf};
6
7pub const CACHE_DIR: &str = ".omni";
8pub const MANIFEST_FILE: &str = "manifest.json";
9pub const STATE_FILE: &str = "state.bin";
10pub const BM25_FILE: &str = "bm25.bin";
11
12#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
13pub struct FileFingerprint {
14    pub mtime_ms: u64,
15    pub size_bytes: u64,
16}
17
18#[derive(Debug, Clone, Serialize, Deserialize, Default)]
19pub struct IndexManifest {
20    pub tool_version: String,
21    pub root: Option<String>,
22    pub files: HashMap<String, FileFingerprint>,
23}
24
25pub fn cache_dir(root: &Path) -> PathBuf {
26    root.join(CACHE_DIR)
27}
28
29pub fn ensure_cache_dir(root: &Path) -> Result<PathBuf> {
30    let dir = cache_dir(root);
31    fs::create_dir_all(&dir)
32        .with_context(|| format!("Failed to create cache dir: {}", dir.display()))?;
33    Ok(dir)
34}
35
36pub fn manifest_path(root: &Path) -> PathBuf {
37    cache_dir(root).join(MANIFEST_FILE)
38}
39
40pub fn state_path(root: &Path) -> PathBuf {
41    cache_dir(root).join(STATE_FILE)
42}
43
44pub fn bm25_path(root: &Path) -> PathBuf {
45    cache_dir(root).join(BM25_FILE)
46}
47
48pub fn load_manifest(root: &Path) -> Result<Option<IndexManifest>> {
49    let path = manifest_path(root);
50    if !path.exists() {
51        return Ok(None);
52    }
53    let data =
54        fs::read(&path).with_context(|| format!("Failed to read manifest: {}", path.display()))?;
55    let manifest: IndexManifest = serde_json::from_slice(&data)
56        .with_context(|| format!("Failed to parse manifest: {}", path.display()))?;
57    Ok(Some(manifest))
58}
59
60pub fn save_manifest(root: &Path, manifest: &IndexManifest) -> Result<()> {
61    ensure_cache_dir(root)?;
62    let path = manifest_path(root);
63    let data = serde_json::to_vec_pretty(manifest)?;
64    fs::write(&path, data)
65        .with_context(|| format!("Failed to write manifest: {}", path.display()))?;
66    Ok(())
67}
68
69pub fn clear_cache(root: &Path) -> Result<()> {
70    let dir = cache_dir(root);
71    if dir.exists() {
72        fs::remove_dir_all(&dir)
73            .with_context(|| format!("Failed to remove cache dir: {}", dir.display()))?;
74    }
75    Ok(())
76}