@anysphere/file-service 0.0.0-dacf38fa → 0.0.0-e1f2f04d
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/index.d.ts +1 -0
- package/package.json +7 -7
- package/src/lib.rs +84 -52
- package/src/merkle_tree/local_construction.rs +18 -14
- package/src/merkle_tree/mod.rs +223 -120
package/index.d.ts
CHANGED
|
@@ -11,5 +11,6 @@ export class MerkleClient {
|
|
|
11
11
|
getSubtreeHash(path: string): Promise<string>
|
|
12
12
|
getNumEmbeddableFiles(): Promise<number>
|
|
13
13
|
getAllFiles(): Promise<Array<string>>
|
|
14
|
+
getNextFileToEmbed(): Promise<Array<string>>
|
|
14
15
|
getHashesForFiles(files: Array<string>): Promise<Array<string>>
|
|
15
16
|
}
|
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-e1f2f04d",
|
|
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-e1f2f04d",
|
|
39
|
+
"@anysphere/file-service-darwin-x64": "0.0.0-e1f2f04d",
|
|
40
|
+
"@anysphere/file-service-linux-x64-gnu": "0.0.0-e1f2f04d",
|
|
41
|
+
"@anysphere/file-service-darwin-arm64": "0.0.0-e1f2f04d",
|
|
42
|
+
"@anysphere/file-service-win32-arm64-msvc": "0.0.0-e1f2f04d",
|
|
43
|
+
"@anysphere/file-service-darwin-universal": "0.0.0-e1f2f04d"
|
|
44
44
|
}
|
|
45
45
|
}
|
package/src/lib.rs
CHANGED
|
@@ -3,6 +3,8 @@ pub mod file_utils;
|
|
|
3
3
|
pub mod git_utils;
|
|
4
4
|
pub mod merkle_tree;
|
|
5
5
|
|
|
6
|
+
use std::vec;
|
|
7
|
+
|
|
6
8
|
use merkle_tree::{LocalConstruction, MerkleTree};
|
|
7
9
|
|
|
8
10
|
#[macro_use]
|
|
@@ -31,7 +33,7 @@ impl MerkleClient {
|
|
|
31
33
|
// 3. sync with the remote
|
|
32
34
|
self.compute_merkle_tree().await?;
|
|
33
35
|
|
|
34
|
-
|
|
36
|
+
Ok(())
|
|
35
37
|
}
|
|
36
38
|
|
|
37
39
|
pub async unsafe fn interrupt(&mut self) -> Result<(), napi::Error> {
|
|
@@ -67,57 +69,87 @@ impl MerkleClient {
|
|
|
67
69
|
let _r = self.tree.delete_file(file_path);
|
|
68
70
|
}
|
|
69
71
|
|
|
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
|
-
|
|
72
|
+
#[napi]
|
|
73
|
+
pub async fn get_subtree_hash(
|
|
74
|
+
&self,
|
|
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
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
#[napi]
|
|
89
|
+
pub async fn get_num_embeddable_files(&self) -> Result<i32, napi::Error> {
|
|
90
|
+
let num = self.tree.get_num_embeddable_files().await;
|
|
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
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
#[napi]
|
|
102
|
+
pub async fn get_all_files(&self) -> Result<Vec<String>, napi::Error> {
|
|
103
|
+
let files = self.tree.get_all_files().await;
|
|
104
|
+
|
|
105
|
+
match files {
|
|
106
|
+
Ok(files) => Ok(files),
|
|
107
|
+
Err(e) => Err(napi::Error::new(
|
|
108
|
+
napi::Status::Unknown,
|
|
109
|
+
format!("Error in get_all_files: {:?}", e),
|
|
110
|
+
)),
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
#[napi]
|
|
115
|
+
pub async unsafe fn get_next_file_to_embed(
|
|
116
|
+
&mut self,
|
|
117
|
+
) -> Result<Vec<String>, napi::Error> {
|
|
118
|
+
let n = self.tree.get_next_file_to_embed().await;
|
|
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
|
+
)),
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
#[napi]
|
|
139
|
+
pub async fn get_hashes_for_files(
|
|
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
|
+
}
|
|
152
|
+
}
|
|
121
153
|
|
|
122
154
|
// #[napi]
|
|
123
155
|
pub fn update_root_directory(&mut self, root_directory: String) {
|
|
@@ -9,7 +9,9 @@ use tonic::async_trait;
|
|
|
9
9
|
|
|
10
10
|
#[async_trait]
|
|
11
11
|
impl LocalConstruction for MerkleTree {
|
|
12
|
-
async fn new(
|
|
12
|
+
async fn new(
|
|
13
|
+
root_directory: Option<String>,
|
|
14
|
+
) -> Result<MerkleTree, anyhow::Error> {
|
|
13
15
|
if let Some(root_directory) = root_directory {
|
|
14
16
|
let n = MerkleTree::construct_merkle_tree(root_directory).await;
|
|
15
17
|
return n;
|
|
@@ -25,7 +27,9 @@ impl LocalConstruction for MerkleTree {
|
|
|
25
27
|
/// 2. compute hash for each file
|
|
26
28
|
/// 3. construct merkle tree
|
|
27
29
|
/// 4. return merkle tree
|
|
28
|
-
async fn construct_merkle_tree(
|
|
30
|
+
async fn construct_merkle_tree(
|
|
31
|
+
root_directory: String,
|
|
32
|
+
) -> Result<MerkleTree, anyhow::Error> {
|
|
29
33
|
let path = PathBuf::from(root_directory.clone());
|
|
30
34
|
if !path.exists() {
|
|
31
35
|
// FIXME: we should report this via a good logger.
|
|
@@ -37,6 +41,7 @@ impl LocalConstruction for MerkleTree {
|
|
|
37
41
|
root: root_node,
|
|
38
42
|
files: HashMap::new(),
|
|
39
43
|
root_path: root_directory,
|
|
44
|
+
cursor: None,
|
|
40
45
|
};
|
|
41
46
|
|
|
42
47
|
// we now iterate over all the nodes and add them to the hashmap
|
|
@@ -49,8 +54,8 @@ impl LocalConstruction for MerkleTree {
|
|
|
49
54
|
let node_reader = node.read().await;
|
|
50
55
|
match &node_reader.node_type {
|
|
51
56
|
NodeType::Branch(n) => {
|
|
52
|
-
|
|
53
|
-
|
|
57
|
+
let children = &n.1;
|
|
58
|
+
files.insert(n.0.clone(), File { node: node.clone() });
|
|
54
59
|
for child in children {
|
|
55
60
|
add_nodes_to_hashmap(child, files).await;
|
|
56
61
|
}
|
|
@@ -102,9 +107,9 @@ impl LocalConstruction for MerkleTree {
|
|
|
102
107
|
// File does not exist in the tree, let's add it.
|
|
103
108
|
let e = self.attach_new_node_to_tree(file_path.clone()).await;
|
|
104
109
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
110
|
+
if e.is_err() {
|
|
111
|
+
return Err(anyhow::anyhow!("Could not attach new node to tree!"));
|
|
112
|
+
}
|
|
108
113
|
}
|
|
109
114
|
|
|
110
115
|
Ok(())
|
|
@@ -139,18 +144,17 @@ impl LocalConstruction for MerkleTree {
|
|
|
139
144
|
let parent_node = parent_node.unwrap();
|
|
140
145
|
let mut mut_parent = parent_node.write().await;
|
|
141
146
|
|
|
147
|
+
// BUG(sualeh): need to actually drop everything that is a child here.
|
|
148
|
+
// idea: enumerate all nodes that are children of this through a starts with query on the hashtable.
|
|
149
|
+
// then drop all of them.
|
|
150
|
+
// in opposite order of length.
|
|
142
151
|
|
|
143
|
-
|
|
144
|
-
// idea: enumerate all nodes that are children of this through a starts with query on the hashtable.
|
|
145
|
-
// then drop all of them.
|
|
146
|
-
// in opposite order of length.
|
|
147
|
-
|
|
148
|
-
// then remove the node from the parent and you are done
|
|
152
|
+
// then remove the node from the parent and you are done
|
|
149
153
|
|
|
150
154
|
// Remove the child from the parent node
|
|
151
155
|
match mut_parent.node_type {
|
|
152
156
|
NodeType::Branch(ref mut node) => {
|
|
153
|
-
|
|
157
|
+
let children = &mut node.1;
|
|
154
158
|
let mut found = false;
|
|
155
159
|
let mut index = 0;
|
|
156
160
|
|
package/src/merkle_tree/mod.rs
CHANGED
|
@@ -13,6 +13,7 @@ pub struct MerkleTree {
|
|
|
13
13
|
root_path: String,
|
|
14
14
|
root: MerkleNodePtr,
|
|
15
15
|
files: HashMap<String, File>,
|
|
16
|
+
cursor: Option<MerkleNodePtr>,
|
|
16
17
|
}
|
|
17
18
|
|
|
18
19
|
#[derive(Debug)]
|
|
@@ -50,12 +51,19 @@ fn get_id() -> i32 {
|
|
|
50
51
|
|
|
51
52
|
#[async_trait]
|
|
52
53
|
pub trait LocalConstruction {
|
|
53
|
-
async fn new(
|
|
54
|
-
|
|
54
|
+
async fn new(
|
|
55
|
+
root_directory: Option<String>,
|
|
56
|
+
) -> Result<MerkleTree, anyhow::Error>;
|
|
57
|
+
|
|
58
|
+
async fn construct_merkle_tree(
|
|
59
|
+
root_directory: String,
|
|
60
|
+
) -> Result<MerkleTree, anyhow::Error>;
|
|
61
|
+
|
|
55
62
|
async fn update_file(
|
|
56
63
|
&mut self,
|
|
57
64
|
file_path: String,
|
|
58
65
|
) -> Result<(), anyhow::Error>;
|
|
66
|
+
|
|
59
67
|
async fn delete_file(
|
|
60
68
|
&mut self,
|
|
61
69
|
file_path: String,
|
|
@@ -81,94 +89,183 @@ impl MerkleTree {
|
|
|
81
89
|
root: Arc::new(RwLock::new(MerkleNode::empty_node(None, None))),
|
|
82
90
|
files: HashMap::new(),
|
|
83
91
|
root_path: "".to_string(),
|
|
92
|
+
cursor: None,
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
pub async fn get_subtree_hash(
|
|
97
|
+
&self,
|
|
98
|
+
path: String,
|
|
99
|
+
) -> Result<String, anyhow::Error> {
|
|
100
|
+
let path = PathBuf::from(path);
|
|
101
|
+
let node = match self.files.get(path.to_str().unwrap()) {
|
|
102
|
+
Some(file) => file.node.clone(),
|
|
103
|
+
None => {
|
|
104
|
+
return Err(anyhow::anyhow!("Could not find file in tree!"));
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
let node_reader = node.read().await;
|
|
109
|
+
let node_hash = node_reader.hash.clone();
|
|
110
|
+
|
|
111
|
+
Ok(node_hash)
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
pub async fn get_num_embeddable_files(&self) -> Result<i32, anyhow::Error> {
|
|
115
|
+
let mut count = 0;
|
|
116
|
+
|
|
117
|
+
for (_, file) in &self.files {
|
|
118
|
+
let file_reader = file.node.read().await;
|
|
119
|
+
match &file_reader.node_type {
|
|
120
|
+
NodeType::File(_) => {
|
|
121
|
+
count += 1;
|
|
122
|
+
}
|
|
123
|
+
NodeType::Branch(_) => {
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
NodeType::ErrorNode(_) => {
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
Ok(count)
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
pub async fn get_all_files(&self) -> Result<Vec<String>, anyhow::Error> {
|
|
136
|
+
let mut files = Vec::new();
|
|
137
|
+
|
|
138
|
+
for (file_name, file) in &self.files {
|
|
139
|
+
let file_reader = file.node.read().await;
|
|
140
|
+
match &file_reader.node_type {
|
|
141
|
+
NodeType::File(_) => {
|
|
142
|
+
files.push(file_name.clone());
|
|
143
|
+
}
|
|
144
|
+
NodeType::Branch(_) => {
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
147
|
+
NodeType::ErrorNode(_) => {
|
|
148
|
+
continue;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
Ok(files)
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
pub async fn get_hashes_for_files(
|
|
157
|
+
&self,
|
|
158
|
+
files: Vec<String>,
|
|
159
|
+
) -> Result<Vec<String>, anyhow::Error> {
|
|
160
|
+
let mut hashes = Vec::new();
|
|
161
|
+
|
|
162
|
+
for file_name in files {
|
|
163
|
+
let file = match self.files.get(&file_name) {
|
|
164
|
+
Some(file) => file,
|
|
165
|
+
None => {
|
|
166
|
+
return Err(anyhow::anyhow!("Could not find file in tree!"));
|
|
167
|
+
}
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
let file_reader = file.node.read().await;
|
|
171
|
+
match &file_reader.node_type {
|
|
172
|
+
NodeType::File(_) => {
|
|
173
|
+
hashes.push(file_reader.hash.clone());
|
|
174
|
+
}
|
|
175
|
+
NodeType::Branch(_) => {
|
|
176
|
+
continue;
|
|
177
|
+
}
|
|
178
|
+
NodeType::ErrorNode(_) => {
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
84
182
|
}
|
|
183
|
+
|
|
184
|
+
Ok(hashes)
|
|
85
185
|
}
|
|
86
186
|
|
|
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
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
}
|
|
160
|
-
NodeType::Branch(_) => {
|
|
161
|
-
continue;
|
|
162
|
-
}
|
|
163
|
-
NodeType::ErrorNode(_) => {
|
|
164
|
-
continue;
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
Ok(hashes)
|
|
170
|
-
}
|
|
187
|
+
/// Returns a filename, and then a path from its parent to the root (which can possibly be empty.)
|
|
188
|
+
pub async fn get_next_file_to_embed(
|
|
189
|
+
&mut self,
|
|
190
|
+
) -> Result<(String, Vec<String>), anyhow::Error> {
|
|
191
|
+
// the plan is to do an in-order traversal of the tree.
|
|
192
|
+
|
|
193
|
+
// first the edge case to deal with:
|
|
194
|
+
// cursor == None
|
|
195
|
+
if self.cursor.is_none() {
|
|
196
|
+
// If the root is a file, return its name.
|
|
197
|
+
if let NodeType::File(file_path) = &self.root.read().await.node_type {
|
|
198
|
+
return Ok((file_path.clone(), vec![]));
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// if the path is not empty, we can iterate till we find the first child.
|
|
202
|
+
let mut potential_first_child = self.root.clone();
|
|
203
|
+
let mut is_branch = true;
|
|
204
|
+
let mut path = Vec::new();
|
|
205
|
+
|
|
206
|
+
while is_branch {
|
|
207
|
+
let node = {
|
|
208
|
+
let potential_first_child_reader = potential_first_child.read().await;
|
|
209
|
+
match &potential_first_child_reader.node_type {
|
|
210
|
+
NodeType::Branch(branch) => branch.clone(),
|
|
211
|
+
NodeType::File(_) => {
|
|
212
|
+
return Err(anyhow::anyhow!(
|
|
213
|
+
"get_next_file_to_embed: This should not happen! the branch happened to be file."
|
|
214
|
+
));
|
|
215
|
+
}
|
|
216
|
+
NodeType::ErrorNode(_) => {
|
|
217
|
+
return Err(anyhow::anyhow!("Cursor is an error node!"));
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
let current_node_name = &node.0;
|
|
223
|
+
let child_list = &node.1;
|
|
224
|
+
|
|
225
|
+
if let Some(c) = child_list.first() {
|
|
226
|
+
let c_reader = c.read().await;
|
|
227
|
+
|
|
228
|
+
match &c_reader.node_type {
|
|
229
|
+
NodeType::File(file_path) => {
|
|
230
|
+
// must set the cursor!
|
|
231
|
+
self.cursor = Some(c.clone());
|
|
232
|
+
|
|
233
|
+
return Ok((file_path.clone(), path));
|
|
234
|
+
}
|
|
235
|
+
NodeType::Branch(_) => {
|
|
236
|
+
potential_first_child = c.clone();
|
|
237
|
+
is_branch = true;
|
|
238
|
+
|
|
239
|
+
// add the path to the current node.
|
|
240
|
+
path.push(current_node_name.clone());
|
|
241
|
+
}
|
|
242
|
+
NodeType::ErrorNode(_) => {
|
|
243
|
+
return Err(anyhow::anyhow!("Cursor is an error node!"));
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
} else {
|
|
247
|
+
// If the root has no children, return an error.
|
|
248
|
+
return Err(anyhow::anyhow!("Root has no children!"));
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// THE DEFAULT CASE:
|
|
254
|
+
// we already have a cursor at a file.
|
|
255
|
+
|
|
256
|
+
// UNWRAP checked and fine. see the none case above.
|
|
257
|
+
let cursor_name = self.cursor.as_ref().unwrap();
|
|
258
|
+
let cursor_reader = cursor_name.read().await;
|
|
171
259
|
|
|
260
|
+
// invariant: you must be a file!!
|
|
261
|
+
|
|
262
|
+
// everytime we get to a child list, we will add all the children to a fifo, and then pull from it as long as we need it.
|
|
263
|
+
|
|
264
|
+
// algorithm:
|
|
265
|
+
// 1.
|
|
266
|
+
|
|
267
|
+
Err(anyhow::anyhow!("Could not find file to embed!"))
|
|
268
|
+
}
|
|
172
269
|
|
|
173
270
|
/// creates a new node and attaches it to the current tree.
|
|
174
271
|
/// SPEC:
|
|
@@ -234,7 +331,7 @@ impl MerkleTree {
|
|
|
234
331
|
}
|
|
235
332
|
};
|
|
236
333
|
|
|
237
|
-
|
|
334
|
+
Ok(new_node)
|
|
238
335
|
}
|
|
239
336
|
|
|
240
337
|
/// Spec:
|
|
@@ -298,17 +395,21 @@ impl MerkleTree {
|
|
|
298
395
|
/// - attaches to the ancestor.
|
|
299
396
|
/// - adds to the filemap
|
|
300
397
|
/// - updates hashes of ancestor path.
|
|
301
|
-
async fn attach_new_node_to_tree(
|
|
398
|
+
async fn attach_new_node_to_tree(
|
|
399
|
+
&mut self,
|
|
400
|
+
file_path: String,
|
|
401
|
+
) -> Result<(), anyhow::Error> {
|
|
302
402
|
let path = PathBuf::from(file_path.clone());
|
|
303
403
|
match self.create_new_node_and_attach_to_ancestors(path).await {
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
404
|
+
Ok(node_ptr) => {
|
|
405
|
+
self.add_subtree_to_filemap(node_ptr).await;
|
|
406
|
+
Ok(())
|
|
407
|
+
}
|
|
408
|
+
Err(e) => Err(anyhow::anyhow!(
|
|
409
|
+
"Could not create new node and attach to ancestors! {}",
|
|
410
|
+
e.to_string()
|
|
411
|
+
)),
|
|
412
|
+
}
|
|
312
413
|
}
|
|
313
414
|
|
|
314
415
|
/// MUTATES MUTATES MUTATES
|
|
@@ -389,20 +490,22 @@ impl MerkleTree {
|
|
|
389
490
|
.create_new_node_and_attach_to_ancestors(file_path)
|
|
390
491
|
.await;
|
|
391
492
|
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
493
|
+
match node_ptr {
|
|
494
|
+
Ok(node_ptr) => {
|
|
495
|
+
self.files.insert(
|
|
496
|
+
file_string,
|
|
497
|
+
File {
|
|
498
|
+
node: node_ptr.clone(),
|
|
499
|
+
},
|
|
500
|
+
);
|
|
501
|
+
}
|
|
502
|
+
Err(e) => {
|
|
503
|
+
return Err(anyhow::anyhow!(
|
|
504
|
+
"Could not create new node and attach to ancestors! {}",
|
|
505
|
+
e.to_string()
|
|
506
|
+
));
|
|
507
|
+
}
|
|
508
|
+
}
|
|
406
509
|
|
|
407
510
|
Ok(())
|
|
408
511
|
}
|
|
@@ -532,15 +635,15 @@ impl MerkleNode {
|
|
|
532
635
|
));
|
|
533
636
|
}
|
|
534
637
|
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
638
|
+
// check if the directory fails the bad dir test.
|
|
639
|
+
let is_bad_dir = file_utils::is_in_bad_dir(file_or_directory);
|
|
640
|
+
if is_bad_dir.is_err() || is_bad_dir.unwrap_or(false) {
|
|
641
|
+
// println!("skipping directory: {}", path_str);
|
|
642
|
+
return Arc::new(RwLock::new(MerkleNode::empty_node(
|
|
643
|
+
Some(file_or_directory),
|
|
644
|
+
Some("Directory is in bad dir!".to_string()),
|
|
645
|
+
)));
|
|
646
|
+
}
|
|
544
647
|
|
|
545
648
|
let entries = fs::read_dir(file_or_directory);
|
|
546
649
|
match entries {
|
|
@@ -655,7 +758,7 @@ impl MerkleNode {
|
|
|
655
758
|
Ok(node) => node,
|
|
656
759
|
Err(e) => {
|
|
657
760
|
// println!("constructing error node. error: {}", e);
|
|
658
|
-
|
|
761
|
+
// println!("file_path: {:?}", file_path);
|
|
659
762
|
MerkleNode::empty_node(Some(file_path), Some(e))
|
|
660
763
|
}
|
|
661
764
|
};
|