@anysphere/file-service 0.0.0-a48d29cb → 0.0.0-ac774178

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/Cargo.toml CHANGED
@@ -17,9 +17,6 @@ tempfile = "3.8.0"
17
17
  anyhow = "1.0.75"
18
18
  tonic = "0.9.2"
19
19
  prost = "0.11.9"
20
- tracing = "0.1.37"
21
- tracing-subscriber = "0.3.17"
22
- tracing-appender = "0.2.2"
23
20
 
24
21
  [build-dependencies]
25
22
  napi-build = "2.0.1"
package/index.d.ts CHANGED
@@ -6,15 +6,10 @@
6
6
  export class MerkleClient {
7
7
  constructor(rootDirectory: string)
8
8
  init(): Promise<void>
9
- computeMerkleTree(): Promise<void>
10
9
  updateFile(filePath: string): Promise<void>
11
10
  deleteFile(filePath: string): Promise<void>
12
- getSubtreeHash(relativePath: string): Promise<string>
11
+ getSubtreeHash(path: string): Promise<string>
13
12
  getNumEmbeddableFiles(): Promise<number>
14
13
  getAllFiles(): Promise<Array<string>>
15
- getAllDirFilesToEmbed(absoluteFilePath: string): Promise<Array<string>>
16
- getNextFileToEmbed(): Promise<Array<string>>
17
- getSpline(absoluteFilePath: string): Promise<Array<string>>
18
14
  getHashesForFiles(files: Array<string>): Promise<Array<string>>
19
- updateRootDirectory(rootDirectory: string): void
20
15
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@anysphere/file-service",
3
- "version": "0.0.0-a48d29cb",
3
+ "version": "0.0.0-ac774178",
4
4
  "main": "index.js",
5
5
  "types": "index.d.ts",
6
6
  "napi": {
@@ -35,11 +35,11 @@
35
35
  "version": "napi version"
36
36
  },
37
37
  "optionalDependencies": {
38
- "@anysphere/file-service-win32-x64-msvc": "0.0.0-a48d29cb",
39
- "@anysphere/file-service-darwin-x64": "0.0.0-a48d29cb",
40
- "@anysphere/file-service-linux-x64-gnu": "0.0.0-a48d29cb",
41
- "@anysphere/file-service-darwin-arm64": "0.0.0-a48d29cb",
42
- "@anysphere/file-service-win32-arm64-msvc": "0.0.0-a48d29cb",
43
- "@anysphere/file-service-darwin-universal": "0.0.0-a48d29cb"
38
+ "@anysphere/file-service-win32-x64-msvc": "0.0.0-ac774178",
39
+ "@anysphere/file-service-darwin-x64": "0.0.0-ac774178",
40
+ "@anysphere/file-service-linux-x64-gnu": "0.0.0-ac774178",
41
+ "@anysphere/file-service-darwin-arm64": "0.0.0-ac774178",
42
+ "@anysphere/file-service-win32-arm64-msvc": "0.0.0-ac774178",
43
+ "@anysphere/file-service-darwin-universal": "0.0.0-ac774178"
44
44
  }
45
45
  }
package/src/file_utils.rs CHANGED
@@ -12,8 +12,9 @@ pub fn is_in_bad_dir(file_path: &Path) -> Result<bool, Error> {
12
12
  let item_path = file_path
13
13
  .to_str()
14
14
  .ok_or(anyhow::anyhow!("Failed to convert path to string"))?;
15
- let is_bad_dir =
16
- item_path.contains("node_modules") || item_path.contains(".git");
15
+ let is_bad_dir = (item_path.contains("node_modules")
16
+ || item_path.contains(".git"))
17
+ && !(item_path.ends_with(".git") || item_path.ends_with("node_modules"));
17
18
  Ok(is_bad_dir)
18
19
  }
19
20
 
@@ -37,14 +38,14 @@ pub fn is_good_file(file_path: &Path) -> Result<(), Error> {
37
38
 
38
39
  match file_name {
39
40
  "package-lock.json" | "pnpm-lock.yaml" | "yarn.lock" | "composer.lock"
40
- | "Gemfile.lock" | "bun.lockb" => {
41
+ | "Gemfile.lock" => {
41
42
  return Err(anyhow::anyhow!("File is just a lock file"));
42
43
  }
43
44
  _ => {}
44
45
  }
45
46
 
46
47
  match extension {
47
- "lock" | "bak" | "tmp" | "bin" | "exe" | "dll" | "so" | "lockb" => {
48
+ "lock" | "bak" | "tmp" | "bin" | "exe" | "dll" | "so" => {
48
49
  return Err(anyhow::anyhow!("File is just a lock file"));
49
50
  }
50
51
  _ => {}
package/src/git_utils.rs CHANGED
@@ -1,10 +1,10 @@
1
1
  use std::collections::HashSet;
2
+ use std::path::PathBuf;
2
3
  use std::process::Command;
3
4
 
4
5
  pub fn list_ignored_files(
5
6
  workspace_root_path: &str,
6
- should_return_absolute_paths: bool,
7
- ) -> Result<HashSet<String>, Box<dyn std::error::Error>> {
7
+ ) -> Result<HashSet<PathBuf>, Box<dyn std::error::Error>> {
8
8
  let mut gitignored_files = HashSet::new();
9
9
 
10
10
  let commands = vec![
@@ -15,66 +15,12 @@ pub fn list_ignored_files(
15
15
  "--ignored",
16
16
  "--exclude-standard",
17
17
  ],
18
- // FIXME(sualeh): this is super sketchy and might totally break in like a bazillion ways. i dont like it.
19
- vec![
20
- "sh",
21
- "-c",
22
- "git submodule foreach --quiet 'git ls-files --others --ignored --exclude-standard | sed \"s|^|$path/|\"'",
23
- ],
24
- ];
25
-
26
- for command in commands {
27
- let output = Command::new(&command[0])
28
- .args(&command[1..])
29
- .current_dir(workspace_root_path)
30
- .output()?;
31
-
32
- if output.status.success() {
33
- let files = String::from_utf8(output.stdout)?
34
- .lines()
35
- .filter(|line| !line.is_empty())
36
- .map(|line| {
37
- if should_return_absolute_paths {
38
- let mut path = std::path::PathBuf::from(workspace_root_path);
39
- path.push(line);
40
-
41
- match path.canonicalize() {
42
- Ok(canonical_path) => {
43
- canonical_path.to_string_lossy().into_owned()
44
- }
45
- Err(_) => String::from(line),
46
- }
47
- } else {
48
- String::from(line)
49
- }
50
- })
51
- .collect::<HashSet<_>>();
52
-
53
- gitignored_files.extend(files);
54
- }
55
- }
56
-
57
- Ok(gitignored_files)
58
- }
59
-
60
- pub fn list_ignored_files_with_absolute_paths(
61
- workspace_root_path: &str,
62
- ) -> Result<HashSet<String>, Box<dyn std::error::Error>> {
63
- let mut gitignored_files = HashSet::new();
64
-
65
- let commands = vec![
66
18
  vec![
67
19
  "git",
68
- "ls-files",
69
- "--others",
70
- "--ignored",
71
- "--exclude-standard",
72
- ],
73
- // FIXME(sualeh): this is super sketchy and might totally break in like a bazillion ways. i dont like it.
74
- vec![
75
- "sh",
76
- "-c",
77
- "git submodule foreach --quiet 'git ls-files --others --ignored --exclude-standard | sed \"s|^|$path/|\"'",
20
+ "submodule",
21
+ "foreach",
22
+ "--quiet",
23
+ "git ls-files --others --ignored --exclude-standard | sed 's|^|$path/|'",
78
24
  ],
79
25
  ];
80
26
 
@@ -88,7 +34,7 @@ pub fn list_ignored_files_with_absolute_paths(
88
34
  let files = String::from_utf8(output.stdout)?
89
35
  .lines()
90
36
  .filter(|line| !line.is_empty())
91
- .map(|line| String::from(line))
37
+ .map(|line| PathBuf::from(line))
92
38
  .collect::<HashSet<_>>();
93
39
 
94
40
  gitignored_files.extend(files);
@@ -111,18 +57,6 @@ pub async fn is_git_ignored(
111
57
  Ok(output.status.success())
112
58
  }
113
59
 
114
- pub async fn is_git_directory(
115
- workspace_root_path: &str,
116
- ) -> Result<bool, anyhow::Error> {
117
- let output = tokio::process::Command::new("git")
118
- .args(&["rev-parse", "--is-inside-work-tree"])
119
- .current_dir(workspace_root_path)
120
- .output()
121
- .await?;
122
-
123
- Ok(output.status.success())
124
- }
125
-
126
60
  #[cfg(test)]
127
61
  mod tests {
128
62
  use super::*;
@@ -132,8 +66,7 @@ mod tests {
132
66
  #[test]
133
67
  fn test_no_ignored_files() {
134
68
  let dir = tempfile::tempdir().unwrap();
135
- let gitignored_files =
136
- list_ignored_files(dir.path().to_str().unwrap(), false).unwrap();
69
+ let gitignored_files = list_ignored_files(dir.path().to_str().unwrap()).unwrap();
137
70
  Command::new("git")
138
71
  .args(&["init"])
139
72
  .current_dir(dir.path())
@@ -159,14 +92,13 @@ mod tests {
159
92
  .current_dir(dir.path())
160
93
  .output()
161
94
  .unwrap();
162
- let gitignored_files =
163
- list_ignored_files(dir.path().to_str().unwrap(), false).unwrap();
95
+ let gitignored_files = list_ignored_files(dir.path().to_str().unwrap()).unwrap();
164
96
  println!(
165
97
  "ignored files for test_one_ignored_file: {:?}",
166
98
  gitignored_files
167
99
  );
168
100
  // assert_eq!(gitignored_files.len(), 1);
169
- assert!(gitignored_files.contains(&String::from("ignored.txt")));
101
+ assert!(gitignored_files.contains(&PathBuf::from("ignored.txt")));
170
102
  }
171
103
 
172
104
  #[test]
@@ -189,83 +121,19 @@ mod tests {
189
121
  .current_dir(dir.path())
190
122
  .output()
191
123
  .unwrap();
192
- let gitignored_files =
193
- list_ignored_files(dir.path().to_str().unwrap(), false).unwrap();
124
+ let gitignored_files = list_ignored_files(dir.path().to_str().unwrap()).unwrap();
194
125
  println!(
195
126
  "ignored files for test_multiple_ignored_files: {:?}",
196
127
  gitignored_files
197
128
  );
198
129
  // assert_eq!(gitignored_files.len(), 2);
199
- assert!(gitignored_files.contains(&String::from("ignored1.txt")));
200
- assert!(gitignored_files.contains(&String::from("ignored2.txt")));
201
- }
202
-
203
- #[test]
204
- fn test_git_submodule_ignored_files() {
205
- let dir = tempfile::tempdir().unwrap();
206
- let submodule_path = dir.path().join("submodule");
207
- std::fs::create_dir(&submodule_path).unwrap();
208
-
209
- let o = Command::new("git")
210
- .args(&["init"])
211
- .current_dir(&submodule_path)
212
- .output()
213
- .unwrap();
214
- println!("git init output: {:?}", o);
215
-
216
- let file_path = submodule_path.join("ignored.txt");
217
- let mut file = File::create(&file_path).unwrap();
218
- writeln!(file, "This is an ignored file.").unwrap();
219
-
220
- let file2 = submodule_path.join("ignored2.txt");
221
- let mut file = File::create(&file2).unwrap();
222
- writeln!(file, "This is another ignored file.").unwrap();
223
-
224
- let gitignore_path = submodule_path.join(".gitignore");
225
- let mut gitignore = File::create(&gitignore_path).unwrap();
226
- writeln!(gitignore, "*.txt").unwrap();
227
-
228
- let o = Command::new("git")
229
- .args(&["init"])
230
- .current_dir(dir.path())
231
- .output()
232
- .unwrap();
233
- println!("git init output: {:?}", o);
234
-
235
- // make a commit in the submodule
236
- let o = Command::new("git")
237
- .args(&["add", "."])
238
- .current_dir(&submodule_path)
239
- .output()
240
- .unwrap();
241
- println!("git add output: {:?}", o);
242
- let o = Command::new("git")
243
- .args(&["commit", "-m", "initial commit"])
244
- .current_dir(&submodule_path)
245
- .output()
246
- .unwrap();
247
- println!("git commit output: {:?}", o);
248
-
249
- let o = Command::new("git")
250
- .args(&["submodule", "add", "./submodule"])
251
- .current_dir(dir.path())
252
- .output()
253
- .unwrap();
254
- println!("git submodule add output: {:?}", o);
255
-
256
- let gitignored_files =
257
- list_ignored_files(dir.path().to_str().unwrap(), false).unwrap();
258
- println!(
259
- "ignored files for test_git_submodule_ignored_files: {:?}",
260
- gitignored_files
261
- );
262
- assert!(gitignored_files.contains(&String::from("submodule/ignored.txt")));
263
- assert!(gitignored_files.contains(&String::from("submodule/ignored2.txt")));
130
+ assert!(gitignored_files.contains(&PathBuf::from("ignored1.txt")));
131
+ assert!(gitignored_files.contains(&PathBuf::from("ignored2.txt")));
264
132
  }
265
133
 
266
134
  #[test]
267
135
  fn test_multiple_ignored_files_in_current_dir() {
268
- let gitignored_files = list_ignored_files(".", false).unwrap();
136
+ let gitignored_files = list_ignored_files(".").unwrap();
269
137
  assert!(gitignored_files.len() > 1);
270
138
 
271
139
  // print a sample of the ignored files
@@ -279,6 +147,7 @@ mod tests {
279
147
  }
280
148
  }
281
149
 
150
+
282
151
  #[tokio::test]
283
152
  async fn test_file_not_ignored() {
284
153
  let dir = tempfile::tempdir().unwrap();
@@ -291,10 +160,7 @@ mod tests {
291
160
  .current_dir(dir.path())
292
161
  .output()
293
162
  .unwrap();
294
- let is_ignored =
295
- is_git_ignored(dir.path().to_str().unwrap(), "not_ignored.txt")
296
- .await
297
- .unwrap();
163
+ let is_ignored = is_git_ignored(dir.path().to_str().unwrap(), "not_ignored.txt").await.unwrap();
298
164
  assert_eq!(is_ignored, false);
299
165
  }
300
166
 
@@ -314,10 +180,7 @@ mod tests {
314
180
  .current_dir(dir.path())
315
181
  .output()
316
182
  .unwrap();
317
- let is_ignored =
318
- is_git_ignored(dir.path().to_str().unwrap(), "ignored.txt")
319
- .await
320
- .unwrap();
183
+ let is_ignored = is_git_ignored(dir.path().to_str().unwrap(), "ignored.txt").await.unwrap();
321
184
  assert_eq!(is_ignored, true);
322
185
  }
323
186
 
@@ -337,10 +200,8 @@ mod tests {
337
200
  .current_dir(dir.path())
338
201
  .output()
339
202
  .unwrap();
340
- let is_ignored =
341
- is_git_ignored(dir.path().to_str().unwrap(), "ignored.txt")
342
- .await
343
- .unwrap();
203
+ let is_ignored = is_git_ignored(dir.path().to_str().unwrap(), "ignored.txt").await.unwrap();
344
204
  assert_eq!(is_ignored, true);
345
205
  }
206
+
346
207
  }
package/src/lib.rs CHANGED
@@ -1,15 +1,9 @@
1
1
  #![deny(clippy::all)]
2
- #![deny(unsafe_op_in_unsafe_fn)]
3
2
  pub mod file_utils;
4
3
  pub mod git_utils;
5
4
  pub mod merkle_tree;
6
5
 
7
- use std::vec;
8
-
9
6
  use merkle_tree::{LocalConstruction, MerkleTree};
10
- use tracing::{info, Level};
11
- use tracing_appender::rolling::{RollingFileAppender, Rotation};
12
- use tracing_subscriber::fmt;
13
7
 
14
8
  #[macro_use]
15
9
  extern crate napi_derive;
@@ -18,35 +12,15 @@ extern crate napi_derive;
18
12
  pub struct MerkleClient {
19
13
  tree: MerkleTree,
20
14
  root_directory: String,
21
- _guard: tracing_appender::non_blocking::WorkerGuard,
22
- }
23
-
24
- pub fn init_logger() -> tracing_appender::non_blocking::WorkerGuard {
25
- let file_appender =
26
- RollingFileAppender::new(Rotation::NEVER, "./", "rust_log.txt");
27
- let (non_blocking, _guard) = tracing_appender::non_blocking(file_appender);
28
- let subscriber = fmt::Subscriber::builder()
29
- .with_max_level(Level::TRACE)
30
- .with_writer(non_blocking)
31
- .with_ansi(false)
32
- .with_line_number(true)
33
- .finish();
34
-
35
- let _ = tracing::subscriber::set_global_default(subscriber);
36
-
37
- _guard
38
15
  }
39
16
 
40
17
  #[napi]
41
18
  impl MerkleClient {
42
19
  #[napi(constructor)]
43
20
  pub fn new(root_directory: String) -> MerkleClient {
44
- let _guard = init_logger();
45
-
46
21
  MerkleClient {
47
22
  tree: MerkleTree::empty_tree(),
48
23
  root_directory,
49
- _guard,
50
24
  }
51
25
  }
52
26
 
@@ -55,36 +29,22 @@ impl MerkleClient {
55
29
  // 1. compute the merkle tree
56
30
  // 2. update the backend
57
31
  // 3. sync with the remote
58
- info!("Merkle tree compute started!");
59
- unsafe {
60
- self.compute_merkle_tree().await?;
61
- }
32
+ self.compute_merkle_tree().await?;
62
33
 
63
- Ok(())
34
+ Ok(())
64
35
  }
65
36
 
66
37
  pub async unsafe fn interrupt(&mut self) -> Result<(), napi::Error> {
67
38
  unimplemented!("Interrupt is not implemented yet");
68
39
  }
69
40
 
70
- #[napi]
41
+ // #[napi]
71
42
  pub async unsafe fn compute_merkle_tree(
72
43
  &mut self,
73
44
  ) -> Result<(), napi::Error> {
74
45
  let t =
75
46
  MerkleTree::construct_merkle_tree(self.root_directory.clone()).await;
76
47
 
77
- let files = self.tree.get_all_files().await;
78
-
79
- match files {
80
- Ok(files) => {
81
- info!("files: {:?}", files);
82
- }
83
- Err(e) => {
84
- info!("Error in get_all_files: {:?}", e);
85
- }
86
- }
87
-
88
48
  match t {
89
49
  Ok(tree) => {
90
50
  self.tree = tree;
@@ -107,152 +67,59 @@ impl MerkleClient {
107
67
  let _r = self.tree.delete_file(file_path);
108
68
  }
109
69
 
110
- #[napi]
111
- pub async fn get_subtree_hash(
112
- &self,
113
- relative_path: String,
114
- ) -> Result<String, napi::Error> {
115
- let absolute_path =
116
- std::path::Path::new(&self.root_directory).join(relative_path);
117
- let canonical_path = absolute_path.canonicalize().unwrap();
118
-
119
- let hash = self.tree.get_subtree_hash(canonical_path).await;
120
-
121
- match hash {
122
- Ok(hash) => Ok(hash),
123
- Err(e) => Err(napi::Error::new(
124
- napi::Status::Unknown,
125
- format!("Error in get_subtree_hash: {:?}", e),
126
- )),
127
- }
128
- }
129
-
130
- #[napi]
131
- pub async fn get_num_embeddable_files(&self) -> Result<i32, napi::Error> {
132
- let num = self.tree.get_num_embeddable_files().await;
133
-
134
- match num {
135
- Ok(num) => Ok(num),
136
- Err(e) => Err(napi::Error::new(
137
- napi::Status::Unknown,
138
- format!("Error in get_num_embeddable_files: {:?}", e),
139
- )),
140
- }
141
- }
142
-
143
- pub async fn get_num_embeddable_files_in_subtree(
144
- &self,
145
- relative_path: String,
146
- ) -> Result<i32, napi::Error> {
147
- let absolute_path = std::path::Path::new(&self.root_directory)
148
- .join(relative_path)
149
- .canonicalize()?;
150
-
151
- let num = self
152
- .tree
153
- .get_num_embeddable_files_in_subtree(absolute_path)
154
- .await;
155
-
156
- match num {
157
- Ok(num) => Ok(num),
158
- Err(e) => Err(napi::Error::new(
159
- napi::Status::Unknown,
160
- format!("Error in get_num_embeddable_files_in_subtree: {:?}", e),
161
- )),
162
- }
163
- }
164
-
165
- #[napi]
166
- pub async fn get_all_files(&self) -> Result<Vec<String>, napi::Error> {
167
- let files = self.tree.get_all_files().await;
168
-
169
- match files {
170
- Ok(files) => Ok(files),
171
- Err(e) => Err(napi::Error::new(
172
- napi::Status::Unknown,
173
- format!("Error in get_all_files: {:?}", e),
174
- )),
175
- }
176
- }
177
-
178
- #[napi]
179
- pub async fn get_all_dir_files_to_embed(
180
- &self,
181
- absolute_file_path: String,
182
- ) -> Result<Vec<String>, napi::Error> {
183
- let absolute_path_str = absolute_file_path.as_str();
184
- let files = self
185
- .tree
186
- .get_all_dir_files_to_embed(absolute_path_str)
187
- .await;
188
-
189
- match files {
190
- Ok(files) => Ok(files),
191
- Err(e) => Err(napi::Error::new(
192
- napi::Status::Unknown,
193
- format!("Error in get_all_dir_files_to_embed: {:?}", e),
194
- )),
195
- }
196
- }
197
-
198
- #[napi]
199
- pub async unsafe fn get_next_file_to_embed(
200
- &mut self,
201
- ) -> Result<Vec<String>, napi::Error> {
202
- let n = self.tree.get_next_file_to_embed().await;
203
-
204
- match n {
205
- Ok((file, path)) => {
206
- // now our job is to put the filename as the first element of the path.
207
-
208
- // TODO(sualeh): we should assert that the path is ascending up to the path.
209
-
210
- let ret = vec![file];
211
- let ret = ret.into_iter().chain(path.into_iter()).collect::<Vec<_>>();
212
- Ok(ret)
213
- }
214
- Err(e) => Err(napi::Error::new(
215
- napi::Status::Unknown,
216
- format!("Error in get_next_file_to_embed: {:?}", e),
217
- )),
218
- }
219
- }
220
-
221
- // FIXME(sualeh): get_spline
222
- #[napi]
223
- pub async fn get_spline(
224
- &self,
225
- absolute_file_path: String,
226
- ) -> Result<Vec<String>, napi::Error> {
227
- let absolute_path_str = absolute_file_path.as_str();
228
- let spline = self.tree.get_spline(absolute_path_str).await;
229
-
230
- match spline {
231
- Ok(spline) => Ok(spline),
232
- Err(e) => Err(napi::Error::new(
233
- napi::Status::Unknown,
234
- format!("Error in get_spline: {:?}", e),
235
- )),
236
- }
237
- }
238
-
239
- #[napi]
240
- pub async fn get_hashes_for_files(
241
- &self,
242
- files: Vec<String>,
243
- ) -> Result<Vec<String>, napi::Error> {
244
- let hashes = self.tree.get_hashes_for_files(files).await;
245
-
246
- match hashes {
247
- Ok(hashes) => Ok(hashes),
248
- Err(e) => Err(napi::Error::new(
249
- napi::Status::Unknown,
250
- format!("Error in get_hashes_for_files: {:?}", e),
251
- )),
252
- }
253
- }
254
-
255
- #[napi]
70
+ #[napi]
71
+ pub async fn get_subtree_hash(&self, path: String) -> Result<String, napi::Error> {
72
+ let hash = self.tree.get_subtree_hash(path).await;
73
+
74
+ match hash {
75
+ Ok(hash) => Ok(hash),
76
+ Err(e) => Err(napi::Error::new(
77
+ napi::Status::Unknown,
78
+ format!("Error in get_subtree_hash: {:?}", e),
79
+ )),
80
+ }
81
+ }
82
+
83
+ #[napi]
84
+ pub async fn get_num_embeddable_files(&self) -> Result<i32, napi::Error> {
85
+ let num = self.tree.get_num_embeddable_files().await;
86
+
87
+ match num {
88
+ Ok(num) => Ok(num),
89
+ Err(e) => Err(napi::Error::new(
90
+ napi::Status::Unknown,
91
+ format!("Error in get_num_embeddable_files: {:?}", e),
92
+ )),
93
+ }
94
+ }
95
+
96
+ #[napi]
97
+ pub async fn get_all_files(&self) -> Result<Vec<String>, napi::Error> {
98
+ let files = self.tree.get_all_files().await;
99
+
100
+ match files {
101
+ Ok(files) => Ok(files),
102
+ Err(e) => Err(napi::Error::new(
103
+ napi::Status::Unknown,
104
+ format!("Error in get_all_files: {:?}", e),
105
+ )),
106
+ }
107
+ }
108
+
109
+ #[napi]
110
+ pub async fn get_hashes_for_files(&self, files: Vec<String>) -> Result<Vec<String>, napi::Error> {
111
+ let hashes = self.tree.get_hashes_for_files(files).await;
112
+
113
+ match hashes {
114
+ Ok(hashes) => Ok(hashes),
115
+ Err(e) => Err(napi::Error::new(
116
+ napi::Status::Unknown,
117
+ format!("Error in get_hashes_for_files: {:?}", e),
118
+ )),
119
+ }
120
+ }
121
+
122
+ // #[napi]
256
123
  pub fn update_root_directory(&mut self, root_directory: String) {
257
124
  self.root_directory = root_directory;
258
125
  }