embeddenator_cli/commands/
update.rs1use anyhow::{Context, Result};
6use embeddenator_fs::EmbrFS;
7use embeddenator_io::{read_bincode_file, write_bincode_file};
8use embeddenator_vsa::ReversibleVSAConfig;
9use std::path::PathBuf;
10
11fn load_embrfs(engram: &PathBuf, manifest: &PathBuf) -> Result<EmbrFS> {
13 let engram_data = read_bincode_file(engram)
14 .with_context(|| format!("Failed to read engram file: {}", engram.display()))?;
15 let manifest_data = read_bincode_file(manifest)
16 .with_context(|| format!("Failed to read manifest file: {}", manifest.display()))?;
17
18 Ok(EmbrFS {
19 engram: engram_data,
20 manifest: manifest_data,
21 resonator: None,
22 })
23}
24
25fn save_embrfs(fs: &EmbrFS, engram: &PathBuf, manifest: &PathBuf) -> Result<()> {
27 write_bincode_file(engram, &fs.engram)
28 .with_context(|| format!("Failed to write engram file: {}", engram.display()))?;
29 write_bincode_file(manifest, &fs.manifest)
30 .with_context(|| format!("Failed to write manifest file: {}", manifest.display()))?;
31 Ok(())
32}
33
34pub fn handle_update_add(
35 engram: PathBuf,
36 manifest: PathBuf,
37 file: PathBuf,
38 logical_path: Option<String>,
39 verbose: bool,
40) -> Result<()> {
41 if verbose {
42 println!(
43 "Embeddenator v{} - Incremental Add",
44 env!("CARGO_PKG_VERSION")
45 );
46 println!("===================================");
47 }
48
49 let mut fs = load_embrfs(&engram, &manifest)?;
50 let config = ReversibleVSAConfig::default();
51
52 let logical = logical_path.unwrap_or_else(|| {
53 file.file_name()
54 .map(|s| s.to_string_lossy().to_string())
55 .unwrap_or_else(|| "unnamed".to_string())
56 });
57
58 if verbose {
59 println!("Adding file: {} -> {}", file.display(), logical);
60 }
61
62 fs.add_file(&file, logical.clone(), verbose, &config)
63 .with_context(|| format!("Failed to add file: {}", file.display()))?;
64
65 save_embrfs(&fs, &engram, &manifest)?;
66
67 if verbose {
68 println!("File added successfully: {}", logical);
69 }
70
71 Ok(())
72}
73
74pub fn handle_update_remove(
75 engram: PathBuf,
76 manifest: PathBuf,
77 path: String,
78 verbose: bool,
79) -> Result<()> {
80 if verbose {
81 println!(
82 "Embeddenator v{} - Incremental Remove",
83 env!("CARGO_PKG_VERSION")
84 );
85 println!("======================================");
86 }
87
88 let mut fs = load_embrfs(&engram, &manifest)?;
89
90 if verbose {
91 println!("Removing file: {}", path);
92 }
93
94 fs.remove_file(&path, verbose)
95 .with_context(|| format!("Failed to remove file: {}", path))?;
96
97 save_embrfs(&fs, &engram, &manifest)?;
98
99 if verbose {
100 println!("File marked as deleted: {}", path);
101 println!("Run 'compact' to permanently remove and reclaim space.");
102 }
103
104 Ok(())
105}
106
107pub fn handle_update_modify(
108 engram: PathBuf,
109 manifest: PathBuf,
110 file: PathBuf,
111 logical_path: Option<String>,
112 verbose: bool,
113) -> Result<()> {
114 if verbose {
115 println!(
116 "Embeddenator v{} - Incremental Modify",
117 env!("CARGO_PKG_VERSION")
118 );
119 println!("======================================");
120 }
121
122 let mut fs = load_embrfs(&engram, &manifest)?;
123 let config = ReversibleVSAConfig::default();
124
125 let logical = logical_path.unwrap_or_else(|| {
126 file.file_name()
127 .map(|s| s.to_string_lossy().to_string())
128 .unwrap_or_else(|| "unnamed".to_string())
129 });
130
131 if verbose {
132 println!("Modifying file: {} -> {}", file.display(), logical);
133 }
134
135 fs.modify_file(&file, logical.clone(), verbose, &config)
136 .with_context(|| format!("Failed to modify file: {}", file.display()))?;
137
138 save_embrfs(&fs, &engram, &manifest)?;
139
140 if verbose {
141 println!("File modified successfully: {}", logical);
142 }
143
144 Ok(())
145}
146
147pub fn handle_update_compact(engram: PathBuf, manifest: PathBuf, verbose: bool) -> Result<()> {
148 if verbose {
149 println!(
150 "Embeddenator v{} - Compact Engram",
151 env!("CARGO_PKG_VERSION")
152 );
153 println!("===================================");
154 }
155
156 let mut fs = load_embrfs(&engram, &manifest)?;
157 let config = ReversibleVSAConfig::default();
158
159 let deleted_before = fs.manifest.files.iter().filter(|f| f.deleted).count();
160
161 if deleted_before == 0 {
162 if verbose {
163 println!("No deleted files to compact.");
164 }
165 return Ok(());
166 }
167
168 if verbose {
169 println!("Compacting {} deleted files...", deleted_before);
170 }
171
172 fs.compact(verbose, &config)
173 .context("Failed to compact engram")?;
174
175 save_embrfs(&fs, &engram, &manifest)?;
176
177 if verbose {
178 println!(
179 "Compaction complete. Removed {} deleted entries.",
180 deleted_before
181 );
182 }
183
184 Ok(())
185}