@anysphere/file-service 0.0.0-f12ef7ad → 0.0.0
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/build.rs +30 -30
- package/index.d.ts +3 -6
- package/package.json +6 -11
- package/src/file_utils.rs +16 -43
- package/src/lib.rs +131 -96
- package/src/merkle_tree/local_construction.rs +53 -63
- package/src/merkle_tree/mod.rs +235 -532
- package/src/merkle_tree/remote_sync.rs +36 -36
- package/src/proto/aiserver.v1.rs +12038 -0
- package/src/lib2.rs +0 -212
- package/src/merkle_tree/test.rs +0 -126
- package/src/merkle_tree/test_files/1/test.txt +0 -0
package/build.rs
CHANGED
|
@@ -6,38 +6,38 @@ fn main() -> Result<(), anyhow::Error> {
|
|
|
6
6
|
napi_build::setup();
|
|
7
7
|
|
|
8
8
|
// print the relative path.
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
//
|
|
14
|
-
//
|
|
15
|
-
//
|
|
16
|
-
//
|
|
17
|
-
//
|
|
18
|
-
// // let proto_paths = relevant_protos
|
|
19
|
-
// // .iter()
|
|
20
|
-
// // .map(|proto| Path::join(&include_path, proto))
|
|
21
|
-
// // .collect::<Vec<_>>();
|
|
22
|
-
// let proto_glob = Path::join(&include_path, "aiserver/v1/*.proto");
|
|
23
|
-
// let relevant_protos: Vec<_> = glob::glob(proto_glob.to_str().expect("Failed to convert path to str"))?
|
|
24
|
-
// .filter_map(Result::ok)
|
|
25
|
-
// .collect();
|
|
26
|
-
|
|
9
|
+
let workspace_root = "../../../../../";
|
|
10
|
+
let path = std::path::Path::new(workspace_root).canonicalize()?;
|
|
11
|
+
let include_path = Path::join(&path, "schema");
|
|
12
|
+
|
|
13
|
+
// let relevant_protos = &[
|
|
14
|
+
// "aiserver/v1/repository.proto",
|
|
15
|
+
// "aiserver/v1/symbolic_context.proto",
|
|
16
|
+
// "aiserver/v1/utils.proto"
|
|
17
|
+
// ];
|
|
27
18
|
// let proto_paths = relevant_protos
|
|
28
19
|
// .iter()
|
|
29
|
-
// .map(|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
20
|
+
// .map(|proto| Path::join(&include_path, proto))
|
|
21
|
+
// .collect::<Vec<_>>();
|
|
22
|
+
let proto_glob = Path::join(&include_path, "aiserver/v1/*.proto");
|
|
23
|
+
let relevant_protos: Vec<_> = glob::glob(proto_glob.to_str().expect("Failed to convert path to str"))?
|
|
24
|
+
.filter_map(Result::ok)
|
|
25
|
+
.collect();
|
|
26
|
+
|
|
27
|
+
let proto_paths = relevant_protos
|
|
28
|
+
.iter()
|
|
29
|
+
.map(|proto_path| proto_path.to_str().expect("Failed to convert path to str"))
|
|
30
|
+
.collect::<Vec<_>>();
|
|
31
|
+
let includes = &[include_path.to_str().unwrap()];
|
|
32
|
+
|
|
33
|
+
// print the path
|
|
34
|
+
println!("cargo:rustc-env=INCLUDE_PATH={}", include_path.display());
|
|
35
|
+
|
|
36
|
+
tonic_build::configure()
|
|
37
|
+
.build_server(false)
|
|
38
|
+
.build_transport(true)
|
|
39
|
+
.out_dir("src/proto")
|
|
40
|
+
.compile(&proto_paths, includes)?;
|
|
41
41
|
|
|
42
42
|
|
|
43
43
|
Ok(())
|
package/index.d.ts
CHANGED
|
@@ -4,13 +4,10 @@
|
|
|
4
4
|
/* auto-generated by NAPI-RS */
|
|
5
5
|
|
|
6
6
|
export class MerkleClient {
|
|
7
|
-
constructor(rootDirectory: string)
|
|
8
7
|
init(): Promise<void>
|
|
8
|
+
syncWithRemote(): Promise<void>
|
|
9
|
+
computeMerkleTree(): Promise<void>
|
|
9
10
|
updateFile(filePath: string): Promise<void>
|
|
10
11
|
deleteFile(filePath: string): Promise<void>
|
|
11
|
-
|
|
12
|
-
getNumEmbeddableFiles(): Promise<number>
|
|
13
|
-
getAllFiles(): Promise<Array<string>>
|
|
14
|
-
getNextFileToEmbed(): Promise<Array<string>>
|
|
15
|
-
getHashesForFiles(files: Array<string>): Promise<Array<string>>
|
|
12
|
+
updateRootDirectory(rootDirectory: string): void
|
|
16
13
|
}
|
package/package.json
CHANGED
|
@@ -1,15 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@anysphere/file-service",
|
|
3
|
-
"version": "0.0.0
|
|
3
|
+
"version": "0.0.0",
|
|
4
4
|
"main": "index.js",
|
|
5
5
|
"types": "index.d.ts",
|
|
6
6
|
"napi": {
|
|
7
7
|
"name": "file_service",
|
|
8
8
|
"triples": {
|
|
9
9
|
"additional": [
|
|
10
|
-
"aarch64-apple-darwin"
|
|
11
|
-
"aarch64-pc-windows-msvc",
|
|
12
|
-
"universal-apple-darwin"
|
|
10
|
+
"aarch64-apple-darwin"
|
|
13
11
|
]
|
|
14
12
|
}
|
|
15
13
|
},
|
|
@@ -31,15 +29,12 @@
|
|
|
31
29
|
"prepublishOnly": "napi prepublish -t npm",
|
|
32
30
|
"test": "ava",
|
|
33
31
|
"universal": "napi universal",
|
|
34
|
-
"preversion": "git config --global user.name || git config --global user.name 'Your Name'; git config --global user.email || git config --global user.email 'youremail@example.com'",
|
|
35
32
|
"version": "napi version"
|
|
36
33
|
},
|
|
37
34
|
"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-f12ef7ad",
|
|
43
|
-
"@anysphere/file-service-darwin-universal": "0.0.0-f12ef7ad"
|
|
35
|
+
"@anysphere/file-service-win32-x64-msvc": "0.0.0",
|
|
36
|
+
"@anysphere/file-service-darwin-x64": "0.0.0",
|
|
37
|
+
"@anysphere/file-service-linux-x64-gnu": "0.0.0",
|
|
38
|
+
"@anysphere/file-service-darwin-arm64": "0.0.0"
|
|
44
39
|
}
|
|
45
40
|
}
|
package/src/file_utils.rs
CHANGED
|
@@ -12,16 +12,15 @@ 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 = (item_path.contains("node_modules")
|
|
16
|
-
|| item_path.contains(".git"))
|
|
15
|
+
let is_bad_dir = (item_path.contains("node_modules") || item_path.contains(".git"))
|
|
17
16
|
&& !(item_path.ends_with(".git") || item_path.ends_with("node_modules"));
|
|
18
17
|
Ok(is_bad_dir)
|
|
19
18
|
}
|
|
20
19
|
|
|
21
20
|
pub fn is_good_file(file_path: &Path) -> Result<(), Error> {
|
|
22
|
-
let item_path = file_path
|
|
23
|
-
|
|
24
|
-
|
|
21
|
+
let item_path = file_path.to_str().ok_or(anyhow::anyhow!(
|
|
22
|
+
"Failed to convert path to string"
|
|
23
|
+
))?;
|
|
25
24
|
|
|
26
25
|
let path = Path::new(item_path);
|
|
27
26
|
let file_name = path
|
|
@@ -37,8 +36,7 @@ pub fn is_good_file(file_path: &Path) -> Result<(), Error> {
|
|
|
37
36
|
.ok_or(anyhow::anyhow!("Failed to convert extension to string"))?;
|
|
38
37
|
|
|
39
38
|
match file_name {
|
|
40
|
-
"package-lock.json" | "pnpm-lock.yaml" | "yarn.lock" | "composer.lock"
|
|
41
|
-
| "Gemfile.lock" => {
|
|
39
|
+
"package-lock.json" | "pnpm-lock.yaml" | "yarn.lock" | "composer.lock" | "Gemfile.lock" => {
|
|
42
40
|
return Err(anyhow::anyhow!("File is just a lock file"));
|
|
43
41
|
}
|
|
44
42
|
_ => {}
|
|
@@ -51,10 +49,7 @@ pub fn is_good_file(file_path: &Path) -> Result<(), Error> {
|
|
|
51
49
|
_ => {}
|
|
52
50
|
}
|
|
53
51
|
|
|
54
|
-
if item_path.contains(".git")
|
|
55
|
-
|| item_path.contains(".svn")
|
|
56
|
-
|| item_path.contains(".hg")
|
|
57
|
-
{
|
|
52
|
+
if item_path.contains(".git") || item_path.contains(".svn") || item_path.contains(".hg") {
|
|
58
53
|
return Err(anyhow::anyhow!("File is just a lock file"));
|
|
59
54
|
}
|
|
60
55
|
|
|
@@ -65,39 +60,29 @@ pub fn is_good_file(file_path: &Path) -> Result<(), Error> {
|
|
|
65
60
|
if bad_extensions.contains(&ext_str) {
|
|
66
61
|
return Err(anyhow::anyhow!("File is not a valid UTF-8 string"));
|
|
67
62
|
}
|
|
68
|
-
}
|
|
69
|
-
None =>
|
|
70
|
-
return Err(anyhow::anyhow!("Failed to convert extension to string"))
|
|
71
|
-
}
|
|
63
|
+
},
|
|
64
|
+
None => return Err(anyhow::anyhow!("Failed to convert extension to string")),
|
|
72
65
|
},
|
|
73
66
|
None => return Err(anyhow::anyhow!("Failed to get extension")),
|
|
74
67
|
}
|
|
75
68
|
|
|
76
|
-
// #[cfg(not(test))]
|
|
77
|
-
// {
|
|
78
69
|
let path = Path::new(item_path);
|
|
79
70
|
for part in path.iter() {
|
|
80
71
|
match part.to_str() {
|
|
81
|
-
Some(s) if s.starts_with(".") =>
|
|
82
|
-
return Err(anyhow::anyhow!("File is hidden"))
|
|
83
|
-
}
|
|
72
|
+
Some(s) if s.starts_with(".") => return Err(anyhow::anyhow!("File is hidden")),
|
|
84
73
|
_ => {}
|
|
85
74
|
}
|
|
86
75
|
}
|
|
87
|
-
// }
|
|
88
76
|
|
|
89
77
|
Ok(())
|
|
90
78
|
}
|
|
91
79
|
|
|
92
80
|
// implement the buffer above:
|
|
93
|
-
pub async fn is_good_file_runtime_check(
|
|
94
|
-
file_path: &Path,
|
|
95
|
-
buffer: &[u8],
|
|
96
|
-
) -> Result<(), Error> {
|
|
81
|
+
pub async fn is_good_file_runtime_check(file_path: &Path, buffer: &[u8]) -> Result<(), Error> {
|
|
97
82
|
match get_file_size(file_path).await {
|
|
98
83
|
Ok(size) if size > 2 * 1024 * 1024 => {
|
|
99
84
|
return Err(anyhow::anyhow!("Buffer is too large"));
|
|
100
|
-
}
|
|
85
|
+
},
|
|
101
86
|
Err(e) => return Err(e),
|
|
102
87
|
_ => {}
|
|
103
88
|
}
|
|
@@ -112,10 +97,7 @@ pub async fn is_good_file_runtime_check(
|
|
|
112
97
|
Ok(())
|
|
113
98
|
}
|
|
114
99
|
|
|
115
|
-
pub fn as_relative_path(
|
|
116
|
-
base_path: &Path,
|
|
117
|
-
file_path: &Path,
|
|
118
|
-
) -> Result<String, Error> {
|
|
100
|
+
pub fn as_relative_path(base_path: &Path, file_path: &Path) -> Result<String, Error> {
|
|
119
101
|
let relative_path = file_path.strip_prefix(base_path)?;
|
|
120
102
|
Ok(
|
|
121
103
|
relative_path
|
|
@@ -135,7 +117,7 @@ pub async fn get_file_size(file_path: &Path) -> Result<u64, Error> {
|
|
|
135
117
|
mod tests {
|
|
136
118
|
use super::*;
|
|
137
119
|
use std::path::Path;
|
|
138
|
-
|
|
120
|
+
use tokio::io::AsyncWriteExt;
|
|
139
121
|
|
|
140
122
|
#[test]
|
|
141
123
|
fn test_is_in_bad_dir() {
|
|
@@ -168,12 +150,7 @@ mod tests {
|
|
|
168
150
|
let mut temp_file = fs::File::create(&temp_file_path).await.unwrap();
|
|
169
151
|
temp_file.write_all(b"Hello, world!").await.unwrap();
|
|
170
152
|
let buffer = fs::read(&temp_file_path).await.unwrap();
|
|
171
|
-
assert_eq!(
|
|
172
|
-
is_good_file_runtime_check(&temp_file_path, &buffer)
|
|
173
|
-
.await
|
|
174
|
-
.is_ok(),
|
|
175
|
-
true
|
|
176
|
-
);
|
|
153
|
+
assert_eq!(is_good_file_runtime_check(&temp_file_path, &buffer).await.is_ok(), true);
|
|
177
154
|
temp_dir.close().unwrap();
|
|
178
155
|
|
|
179
156
|
let temp_dir = tempfile::tempdir().unwrap();
|
|
@@ -181,12 +158,7 @@ mod tests {
|
|
|
181
158
|
let mut temp_file = fs::File::create(&temp_file_path).await.unwrap();
|
|
182
159
|
temp_file.write_all(&[0, 159, 146, 150]).await.unwrap(); // Invalid UTF-8 sequence
|
|
183
160
|
let buffer = fs::read(&temp_file_path).await.unwrap();
|
|
184
|
-
assert_eq!(
|
|
185
|
-
is_good_file_runtime_check(&temp_file_path, &buffer)
|
|
186
|
-
.await
|
|
187
|
-
.is_err(),
|
|
188
|
-
true
|
|
189
|
-
);
|
|
161
|
+
assert_eq!(is_good_file_runtime_check(&temp_file_path, &buffer).await.is_err(), true);
|
|
190
162
|
temp_dir.close().unwrap();
|
|
191
163
|
}
|
|
192
164
|
|
|
@@ -210,5 +182,6 @@ mod tests {
|
|
|
210
182
|
let size = get_file_size(&temp_file_path).await.unwrap();
|
|
211
183
|
assert_eq!(size, 13);
|
|
212
184
|
temp_dir.close().unwrap();
|
|
185
|
+
|
|
213
186
|
}
|
|
214
187
|
}
|
package/src/lib.rs
CHANGED
|
@@ -3,26 +3,52 @@ pub mod file_utils;
|
|
|
3
3
|
pub mod git_utils;
|
|
4
4
|
pub mod merkle_tree;
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
#[path = "proto/aiserver.v1.rs"]
|
|
7
|
+
pub mod aiserver;
|
|
8
|
+
|
|
9
|
+
use aiserver::repository_service_client::RepositoryServiceClient;
|
|
10
|
+
use aiserver::{FastRepoInitHandshakeRequest, GetNumFilesToSendRequest, GetNumFilesToSendResponse};
|
|
11
|
+
use merkle_tree::{MerkleTree, LocalConstruction};
|
|
12
|
+
|
|
13
|
+
use tonic::metadata::MetadataValue;
|
|
14
|
+
use tonic::transport::Channel;
|
|
15
|
+
use tonic::Request;
|
|
16
|
+
// use aiserver::v1::repository_client::RepositoryClient;
|
|
17
|
+
|
|
18
|
+
trait APISualehNeeds {
|
|
19
|
+
fn compute_merkle_tree() -> MerkleTree;
|
|
20
|
+
fn update_file(file_path: String, file_content: String, file_hash: String);
|
|
21
|
+
fn sync_with_remote();
|
|
22
|
+
}
|
|
9
23
|
|
|
10
24
|
#[macro_use]
|
|
11
25
|
extern crate napi_derive;
|
|
12
26
|
|
|
27
|
+
pub type RepositoryClient = RepositoryServiceClient<
|
|
28
|
+
tonic::service::interceptor::InterceptedService<Channel, AsphrAuthInterceptor>,
|
|
29
|
+
>;
|
|
30
|
+
|
|
13
31
|
#[napi]
|
|
14
32
|
pub struct MerkleClient {
|
|
15
33
|
tree: MerkleTree,
|
|
16
34
|
root_directory: String,
|
|
35
|
+
intercepter: AsphrAuthInterceptor,
|
|
36
|
+
backend_url: String,
|
|
37
|
+
// repository_info
|
|
38
|
+
// repo_client: Option<RepositoryClient>,
|
|
17
39
|
}
|
|
18
40
|
|
|
41
|
+
use std::convert::TryFrom;
|
|
42
|
+
|
|
19
43
|
#[napi]
|
|
20
44
|
impl MerkleClient {
|
|
21
|
-
#[napi(constructor)]
|
|
22
|
-
pub fn new(root_directory: String) -> MerkleClient {
|
|
45
|
+
// #[napi(constructor)]
|
|
46
|
+
pub fn new(root_directory: String, bearer_token: String, backend_url: String) -> MerkleClient {
|
|
23
47
|
MerkleClient {
|
|
24
48
|
tree: MerkleTree::empty_tree(),
|
|
25
49
|
root_directory,
|
|
50
|
+
intercepter: AsphrAuthInterceptor::new(bearer_token),
|
|
51
|
+
backend_url,
|
|
26
52
|
}
|
|
27
53
|
}
|
|
28
54
|
|
|
@@ -31,32 +57,83 @@ impl MerkleClient {
|
|
|
31
57
|
// 1. compute the merkle tree
|
|
32
58
|
// 2. update the backend
|
|
33
59
|
// 3. sync with the remote
|
|
34
|
-
self.compute_merkle_tree().await
|
|
60
|
+
self.compute_merkle_tree().await;
|
|
61
|
+
let res = self.sync_with_remote().await;
|
|
62
|
+
|
|
63
|
+
if let Err(e) = res {
|
|
64
|
+
println!("Error: {:?}", e);
|
|
65
|
+
return Err(napi::Error::new(
|
|
66
|
+
napi::Status::Unknown,
|
|
67
|
+
"Error in sync_with_remote",
|
|
68
|
+
));
|
|
69
|
+
}
|
|
35
70
|
|
|
36
71
|
Ok(())
|
|
37
72
|
}
|
|
38
73
|
|
|
39
|
-
pub async
|
|
40
|
-
|
|
74
|
+
pub async fn update_backend(&self) -> Result<RepositoryClient, napi::Error> {
|
|
75
|
+
let channel = match Channel::from_shared(self.backend_url.clone()) {
|
|
76
|
+
Ok(channel) => {
|
|
77
|
+
let connection = match channel.connect().await {
|
|
78
|
+
Ok(connection) => connection,
|
|
79
|
+
Err(_) => {
|
|
80
|
+
return Err(napi::Error::new(
|
|
81
|
+
napi::Status::Unknown,
|
|
82
|
+
"Invalid backend URL",
|
|
83
|
+
))
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
connection
|
|
88
|
+
}
|
|
89
|
+
Err(_) => {
|
|
90
|
+
return Err(napi::Error::new(
|
|
91
|
+
napi::Status::Unknown,
|
|
92
|
+
"Invalid backend URL",
|
|
93
|
+
))
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
let repo_client = RepositoryServiceClient::with_interceptor(channel, self.intercepter.clone());
|
|
98
|
+
|
|
99
|
+
Ok(repo_client)
|
|
41
100
|
}
|
|
42
101
|
|
|
43
|
-
|
|
44
|
-
pub async
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
self.tree = tree;
|
|
53
|
-
Ok(())
|
|
54
|
-
}
|
|
55
|
-
Err(e) => Err(napi::Error::new(
|
|
56
|
-
napi::Status::Unknown,
|
|
57
|
-
format!("Error in compute_merkle_tree: {:?}", e),
|
|
58
|
-
)),
|
|
102
|
+
#[napi]
|
|
103
|
+
pub async fn sync_with_remote(&self) -> Result<(), napi::Error> {
|
|
104
|
+
// BLOCKER:
|
|
105
|
+
// 1. need to get the repository info nicely from javascript.
|
|
106
|
+
// 2. need to handle the napi conversions.
|
|
107
|
+
let client: Result<RepositoryClient, napi::Error> = self.update_backend().await;
|
|
108
|
+
|
|
109
|
+
if let Err(e) = client {
|
|
110
|
+
return Err(e);
|
|
59
111
|
}
|
|
112
|
+
let mut client = client.unwrap();
|
|
113
|
+
|
|
114
|
+
// 1. make sure your tree is upto date.
|
|
115
|
+
// just make sure that you did an update recently and that you havent left too many updates to be buffered up.
|
|
116
|
+
|
|
117
|
+
// 2. sync it carefully.
|
|
118
|
+
// let repo_init_handshake_req = tonic::Request::new(FastRepoInitHandshakeRequest {
|
|
119
|
+
// repository:
|
|
120
|
+
// merkle_tree: self.tree.clone(),
|
|
121
|
+
// });
|
|
122
|
+
// client.fast_repo_init_handshake()
|
|
123
|
+
|
|
124
|
+
// 2.5 if the hash is the same, you are happy and you just leave.
|
|
125
|
+
|
|
126
|
+
// 3. start the diffing process if everything is ok.
|
|
127
|
+
// let different_files = self.tree.sync_with_remote(client).await;
|
|
128
|
+
// let num_files_to_send = different_files.len();
|
|
129
|
+
|
|
130
|
+
// 4. send those files to the server!
|
|
131
|
+
Ok(())
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
#[napi]
|
|
135
|
+
pub async unsafe fn compute_merkle_tree(&mut self) {
|
|
136
|
+
self.tree = MerkleTree::construct_merkle_tree(self.root_directory.clone()).await;
|
|
60
137
|
}
|
|
61
138
|
|
|
62
139
|
#[napi]
|
|
@@ -70,89 +147,47 @@ impl MerkleClient {
|
|
|
70
147
|
}
|
|
71
148
|
|
|
72
149
|
#[napi]
|
|
73
|
-
pub
|
|
74
|
-
|
|
75
|
-
path: String,
|
|
76
|
-
) -> Result<String, napi::Error> {
|
|
77
|
-
let hash = self.tree.get_subtree_hash(path).await;
|
|
78
|
-
|
|
79
|
-
match hash {
|
|
80
|
-
Ok(hash) => Ok(hash),
|
|
81
|
-
Err(e) => Err(napi::Error::new(
|
|
82
|
-
napi::Status::Unknown,
|
|
83
|
-
format!("Error in get_subtree_hash: {:?}", e),
|
|
84
|
-
)),
|
|
85
|
-
}
|
|
150
|
+
pub fn update_root_directory(&mut self, root_directory: String) {
|
|
151
|
+
self.root_directory = root_directory;
|
|
86
152
|
}
|
|
87
153
|
|
|
88
|
-
|
|
89
|
-
pub
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
match num {
|
|
93
|
-
Ok(num) => Ok(num),
|
|
94
|
-
Err(e) => Err(napi::Error::new(
|
|
95
|
-
napi::Status::Unknown,
|
|
96
|
-
format!("Error in get_num_embeddable_files: {:?}", e),
|
|
97
|
-
)),
|
|
98
|
-
}
|
|
154
|
+
// TODO
|
|
155
|
+
pub fn update_repository_info(&mut self, repository_info: String) {
|
|
156
|
+
// self.repository_info = repository_info;
|
|
99
157
|
}
|
|
158
|
+
}
|
|
100
159
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
160
|
+
/// A simple implementation of an interceptor that adds a bearer token to the request
|
|
161
|
+
#[derive(Clone)]
|
|
162
|
+
pub struct AsphrAuthInterceptor {
|
|
163
|
+
auth_token: String,
|
|
164
|
+
full_auth_string: String,
|
|
165
|
+
}
|
|
104
166
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
167
|
+
impl tonic::service::Interceptor for AsphrAuthInterceptor {
|
|
168
|
+
fn call(&mut self, mut request: tonic::Request<()>) -> Result<tonic::Request<()>, tonic::Status> {
|
|
169
|
+
request.metadata_mut().insert(
|
|
170
|
+
"authorization",
|
|
171
|
+
MetadataValue::try_from(&self.full_auth_string).unwrap(),
|
|
172
|
+
);
|
|
173
|
+
Ok(request)
|
|
112
174
|
}
|
|
175
|
+
}
|
|
113
176
|
|
|
114
|
-
|
|
115
|
-
pub
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
match n {
|
|
121
|
-
Ok((file, path)) => {
|
|
122
|
-
// now our job is to put the filename as the first element of the path.
|
|
123
|
-
|
|
124
|
-
// TODO(sualeh): we should assert that the path is ascending up to the path.
|
|
125
|
-
|
|
126
|
-
let ret = vec![file];
|
|
127
|
-
let ret = ret.into_iter().chain(path.into_iter()).collect::<Vec<_>>();
|
|
128
|
-
|
|
129
|
-
Ok(ret)
|
|
130
|
-
}
|
|
131
|
-
Err(e) => Err(napi::Error::new(
|
|
132
|
-
napi::Status::Unknown,
|
|
133
|
-
format!("Error in get_next_file_to_embed: {:?}", e),
|
|
134
|
-
)),
|
|
177
|
+
impl AsphrAuthInterceptor {
|
|
178
|
+
pub fn new(auth_token: String) -> AsphrAuthInterceptor {
|
|
179
|
+
AsphrAuthInterceptor {
|
|
180
|
+
auth_token: auth_token.clone(),
|
|
181
|
+
full_auth_string: format!("Bearer {}", auth_token),
|
|
135
182
|
}
|
|
136
183
|
}
|
|
137
184
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
&self,
|
|
141
|
-
files: Vec<String>,
|
|
142
|
-
) -> Result<Vec<String>, napi::Error> {
|
|
143
|
-
let hashes = self.tree.get_hashes_for_files(files).await;
|
|
144
|
-
|
|
145
|
-
match hashes {
|
|
146
|
-
Ok(hashes) => Ok(hashes),
|
|
147
|
-
Err(e) => Err(napi::Error::new(
|
|
148
|
-
napi::Status::Unknown,
|
|
149
|
-
format!("Error in get_hashes_for_files: {:?}", e),
|
|
150
|
-
)),
|
|
151
|
-
}
|
|
185
|
+
pub fn get_auth_token(&self) -> String {
|
|
186
|
+
self.auth_token.clone()
|
|
152
187
|
}
|
|
153
188
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
self.
|
|
189
|
+
pub fn update_auth_token(&mut self, new_token: String) {
|
|
190
|
+
self.auth_token = new_token;
|
|
191
|
+
self.full_auth_string = format!("Bearer {}", self.auth_token);
|
|
157
192
|
}
|
|
158
193
|
}
|