@@ -8,6 +8,7 @@ mod store;
88
99use anyhow:: Result ;
1010use clap:: { Parser , Subcommand } ;
11+ use std:: io:: { self , BufRead , Write } ;
1112use std:: path:: PathBuf ;
1213use 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+
6488fn 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
0 commit comments