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