Skip to content

Commit f8efee4

Browse files
devwhodevsclaude
andcommitted
feat: wire all modules to CLI subcommands
Connect index, search, status, and clear commands to real module calls. Fix db filename mismatch between indexer (engraph.db) and search (store.db). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent ce8fd29 commit f8efee4

2 files changed

Lines changed: 121 additions & 13 deletions

File tree

src/main.rs

Lines changed: 119 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ mod store;
88

99
use anyhow::Result;
1010
use clap::{Parser, Subcommand};
11+
use std::io::{self, BufRead, Write};
1112
use std::path::PathBuf;
1213
use tracing::info;
1314

@@ -61,6 +62,29 @@ enum Command {
6162
},
6263
}
6364

65+
/// Check whether an index has been built by looking for engraph.db in data_dir.
66+
fn index_exists(data_dir: &std::path::Path) -> bool {
67+
data_dir.join("engraph.db").exists()
68+
}
69+
70+
/// Remove a file, ignoring NotFound errors.
71+
fn remove_if_exists(path: &std::path::Path) -> Result<bool> {
72+
match std::fs::remove_file(path) {
73+
Ok(()) => Ok(true),
74+
Err(e) if e.kind() == io::ErrorKind::NotFound => Ok(false),
75+
Err(e) => Err(e.into()),
76+
}
77+
}
78+
79+
/// Remove a directory recursively, ignoring NotFound errors.
80+
fn remove_dir_if_exists(path: &std::path::Path) -> Result<bool> {
81+
match std::fs::remove_dir_all(path) {
82+
Ok(()) => Ok(true),
83+
Err(e) if e.kind() == io::ErrorKind::NotFound => Ok(false),
84+
Err(e) => Err(e.into()),
85+
}
86+
}
87+
6488
fn main() -> Result<()> {
6589
let cli = Cli::parse();
6690

@@ -74,28 +98,112 @@ fn main() -> Result<()> {
7498
.init();
7599

76100
let mut cfg = Config::load()?;
77-
info!(data_dir = %Config::data_dir()?.display(), "loaded config");
101+
let data_dir = Config::data_dir()?;
102+
info!(data_dir = %data_dir.display(), "loaded config");
78103

79104
match cli.command {
80105
Command::Index { path, rebuild } => {
106+
// Merge CLI vault path over config.
81107
cfg.merge_vault_path(path);
82-
let vault = cfg
83-
.vault_path
84-
.as_deref()
85-
.map(|p| p.display().to_string())
86-
.unwrap_or_else(|| "<not set>".into());
87-
println!("Would index: {vault} (rebuild={rebuild})");
108+
109+
// Fall back to current directory if neither CLI nor config provides a vault path.
110+
let vault_path = match &cfg.vault_path {
111+
Some(p) => p.clone(),
112+
None => {
113+
let cwd = std::env::current_dir()?;
114+
cfg.vault_path = Some(cwd.clone());
115+
cwd
116+
}
117+
};
118+
119+
// Canonicalize to resolve symlinks and relative paths.
120+
let vault_path = vault_path.canonicalize().unwrap_or(vault_path);
121+
122+
// Ensure data directory exists.
123+
std::fs::create_dir_all(&data_dir)?;
124+
125+
// Check for vault mismatch: if store has a different vault path, warn.
126+
let db_path = data_dir.join("engraph.db");
127+
if db_path.exists() && !rebuild {
128+
let store = store::Store::open(&db_path)?;
129+
if let Some(stored_vault) = store.get_meta("vault_path")? {
130+
let stored = PathBuf::from(&stored_vault);
131+
if stored != vault_path {
132+
eprint!(
133+
"Warning: Index was built for '{}'. Re-indexing will replace it. Continue? [y/N] ",
134+
stored.display()
135+
);
136+
io::stderr().flush()?;
137+
let mut answer = String::new();
138+
io::stdin().lock().read_line(&mut answer)?;
139+
if !answer.trim().eq_ignore_ascii_case("y") {
140+
println!("Aborted.");
141+
return Ok(());
142+
}
143+
}
144+
}
145+
}
146+
147+
let result = indexer::run_index(&vault_path, &cfg, rebuild)?;
148+
149+
println!(
150+
"Indexed {} new, {} updated, {} deleted files ({} chunks) in {:.1}s",
151+
result.new_files,
152+
result.updated_files,
153+
result.deleted_files,
154+
result.total_chunks,
155+
result.duration.as_secs_f64(),
156+
);
88157
}
158+
89159
Command::Search { query, top_n } => {
90160
cfg.merge_top_n(top_n);
91-
println!("Would search: \"{query}\" (top_n={})", cfg.top_n);
161+
162+
if !index_exists(&data_dir) {
163+
eprintln!("No index found. Run 'engraph index <path>' first.");
164+
std::process::exit(1);
165+
}
166+
167+
search::run_search(&query, cfg.top_n, cli.json, &data_dir)?;
92168
}
169+
93170
Command::Status => {
94-
let json_flag = cli.json;
95-
println!("Would show status (json={json_flag})");
171+
if !index_exists(&data_dir) {
172+
eprintln!("No index found. Run 'engraph index <path>' first.");
173+
std::process::exit(1);
174+
}
175+
176+
search::run_status(cli.json, &data_dir)?;
96177
}
178+
97179
Command::Clear { all } => {
98-
println!("Would clear cache (all={all})");
180+
if all {
181+
// Delete entire ~/.engraph/ directory.
182+
if remove_dir_if_exists(&data_dir)? {
183+
println!("Removed {}", data_dir.display());
184+
} else {
185+
println!("Nothing to clear (data directory does not exist).");
186+
}
187+
} else {
188+
// Delete only index files: engraph.db and hnsw directory.
189+
let mut deleted_any = false;
190+
191+
let db_path = data_dir.join("engraph.db");
192+
if remove_if_exists(&db_path)? {
193+
println!("Removed {}", db_path.display());
194+
deleted_any = true;
195+
}
196+
197+
let hnsw_dir = data_dir.join("hnsw");
198+
if remove_dir_if_exists(&hnsw_dir)? {
199+
println!("Removed {}", hnsw_dir.display());
200+
deleted_any = true;
201+
}
202+
203+
if !deleted_any {
204+
println!("Nothing to clear (no index files found).");
205+
}
206+
}
99207
}
100208
}
101209

src/search.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ pub fn run_search(query: &str, top_n: usize, json: bool, data_dir: &Path) -> Res
2323
let hnsw_dir = data_dir.join("hnsw");
2424
let index = HnswIndex::load(&hnsw_dir).context("loading HNSW index")?;
2525

26-
let db_path = data_dir.join("store.db");
26+
let db_path = data_dir.join("engraph.db");
2727
let store = Store::open(&db_path).context("opening store")?;
2828

2929
let query_vec = embedder.embed_one(query).context("embedding query")?;
@@ -64,7 +64,7 @@ pub fn run_search(query: &str, top_n: usize, json: bool, data_dir: &Path) -> Res
6464

6565
/// Run the status command and print index information.
6666
pub fn run_status(json: bool, data_dir: &Path) -> Result<()> {
67-
let db_path = data_dir.join("store.db");
67+
let db_path = data_dir.join("engraph.db");
6868
let store = Store::open(&db_path).context("opening store")?;
6969
let stats = store.stats()?;
7070

0 commit comments

Comments
 (0)