@anysphere/file-service 0.0.0-e3fdf62d → 0.0.0-e492c95a
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 +88 -4
- package/index.js +69 -4
- package/package.json +15 -9
- package/.yarnrc.yml +0 -1
- package/Cargo.toml +0 -28
- package/build.rs +0 -44
- package/src/file_utils.rs +0 -214
- package/src/git_utils.rs +0 -207
- package/src/lib.rs +0 -158
- package/src/lib2.rs +0 -212
- package/src/merkle_tree/local_construction.rs +0 -206
- package/src/merkle_tree/mod.rs +0 -982
- package/src/merkle_tree/remote_sync.rs +0 -40
- package/src/merkle_tree/test.rs +0 -126
- package/src/merkle_tree/test_files/1/test.txt +0 -0
|
@@ -1,206 +0,0 @@
|
|
|
1
|
-
use crate::merkle_tree::{
|
|
2
|
-
File, MerkleNode, MerkleNodePtr, NodeType, PinnedFuture,
|
|
3
|
-
};
|
|
4
|
-
|
|
5
|
-
use super::{LocalConstruction, MerkleTree};
|
|
6
|
-
use std::path::PathBuf;
|
|
7
|
-
use std::{collections::HashMap, path::Path, sync::Arc};
|
|
8
|
-
use tonic::async_trait;
|
|
9
|
-
|
|
10
|
-
#[async_trait]
|
|
11
|
-
impl LocalConstruction for MerkleTree {
|
|
12
|
-
async fn new(
|
|
13
|
-
root_directory: Option<String>,
|
|
14
|
-
) -> Result<MerkleTree, anyhow::Error> {
|
|
15
|
-
if let Some(root_directory) = root_directory {
|
|
16
|
-
let n = MerkleTree::construct_merkle_tree(root_directory).await;
|
|
17
|
-
return n;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
Ok(MerkleTree::empty_tree())
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/// Factory method to construct a merkle tree from a given directory
|
|
24
|
-
///
|
|
25
|
-
/// plan:
|
|
26
|
-
/// 1. get all files in the directory
|
|
27
|
-
/// 2. compute hash for each file
|
|
28
|
-
/// 3. construct merkle tree
|
|
29
|
-
/// 4. return merkle tree
|
|
30
|
-
async fn construct_merkle_tree(
|
|
31
|
-
root_directory: String,
|
|
32
|
-
) -> Result<MerkleTree, anyhow::Error> {
|
|
33
|
-
let path = PathBuf::from(root_directory.clone());
|
|
34
|
-
if !path.exists() {
|
|
35
|
-
// FIXME: we should report this via a good logger.
|
|
36
|
-
panic!("Root directory does not exist!");
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
let root_node = MerkleNode::new(path, None).await;
|
|
40
|
-
let mut mt = MerkleTree {
|
|
41
|
-
root: root_node,
|
|
42
|
-
files: HashMap::new(),
|
|
43
|
-
root_path: root_directory,
|
|
44
|
-
cursor: None,
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
// we now iterate over all the nodes and add them to the hashmap
|
|
48
|
-
// TODO(later): i can make this parallel.
|
|
49
|
-
fn add_nodes_to_hashmap<'a>(
|
|
50
|
-
node: &'a MerkleNodePtr,
|
|
51
|
-
files: &'a mut HashMap<String, File>,
|
|
52
|
-
) -> PinnedFuture<'a, ()> {
|
|
53
|
-
Box::pin(async move {
|
|
54
|
-
let node_reader = node.read().await;
|
|
55
|
-
match &node_reader.node_type {
|
|
56
|
-
NodeType::Branch(n) => {
|
|
57
|
-
let children = &n.1;
|
|
58
|
-
files.insert(n.0.clone(), File { node: node.clone() });
|
|
59
|
-
for child in children {
|
|
60
|
-
add_nodes_to_hashmap(child, files).await;
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
NodeType::File(file_name) => {
|
|
64
|
-
let f = File { node: node.clone() };
|
|
65
|
-
files.insert(file_name.clone(), f);
|
|
66
|
-
}
|
|
67
|
-
NodeType::ErrorNode(_) => {
|
|
68
|
-
// do nothing
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
})
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
add_nodes_to_hashmap(&mt.root, &mut mt.files).await;
|
|
75
|
-
|
|
76
|
-
Ok(mt)
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
async fn update_file(
|
|
80
|
-
&mut self,
|
|
81
|
-
file_path: String,
|
|
82
|
-
) -> Result<(), anyhow::Error> {
|
|
83
|
-
// 1. check if the file exists.
|
|
84
|
-
// if it does, then update the file
|
|
85
|
-
// 2. if it does not, then add the file
|
|
86
|
-
|
|
87
|
-
let path = Path::new(&file_path);
|
|
88
|
-
|
|
89
|
-
if !path.exists() {
|
|
90
|
-
return Err(anyhow::anyhow!("File does not exist!"));
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
let path_exists_in_tree = self.files.contains_key(&file_path);
|
|
94
|
-
|
|
95
|
-
if path_exists_in_tree {
|
|
96
|
-
// Update the file in two places.
|
|
97
|
-
let file = self.files.get(&file_path).unwrap();
|
|
98
|
-
|
|
99
|
-
let r = self.update_node(file.node.clone()).await;
|
|
100
|
-
|
|
101
|
-
if r.is_err() {
|
|
102
|
-
// FIXME(sualeh): we should report this via a good logger.
|
|
103
|
-
println!("Could not update node! {}", r.unwrap_err().to_string());
|
|
104
|
-
return Err(anyhow::anyhow!("Could not update node!"));
|
|
105
|
-
}
|
|
106
|
-
} else {
|
|
107
|
-
// File does not exist in the tree, let's add it.
|
|
108
|
-
let e = self.attach_new_node_to_tree(file_path.clone()).await;
|
|
109
|
-
|
|
110
|
-
if e.is_err() {
|
|
111
|
-
return Err(anyhow::anyhow!("Could not attach new node to tree!"));
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
Ok(())
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
async fn delete_file(
|
|
119
|
-
&mut self,
|
|
120
|
-
file_path: String,
|
|
121
|
-
) -> Result<(), anyhow::Error> {
|
|
122
|
-
// 1. check if the file exists.
|
|
123
|
-
// if it does, then delete the file
|
|
124
|
-
//
|
|
125
|
-
// 2. if it does not, then do nothing
|
|
126
|
-
|
|
127
|
-
let path = Path::new(&file_path);
|
|
128
|
-
|
|
129
|
-
if !path.exists() {
|
|
130
|
-
return Err(anyhow::anyhow!("File does not exist!"));
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
let path_exists_in_tree = self.files.contains_key(&file_path);
|
|
134
|
-
|
|
135
|
-
if !path_exists_in_tree {
|
|
136
|
-
return Err(anyhow::anyhow!("File does not exist in the tree!"));
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
// Get the parent node
|
|
140
|
-
let parent_node = self.get_parent_node(&path);
|
|
141
|
-
if parent_node.is_err() {
|
|
142
|
-
return Err(anyhow::anyhow!("Could not get parent node! 0"));
|
|
143
|
-
}
|
|
144
|
-
let parent_node = parent_node.unwrap();
|
|
145
|
-
let mut mut_parent = parent_node.write().await;
|
|
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.
|
|
151
|
-
|
|
152
|
-
// then remove the node from the parent and you are done
|
|
153
|
-
|
|
154
|
-
// Remove the child from the parent node
|
|
155
|
-
match mut_parent.node_type {
|
|
156
|
-
NodeType::Branch(ref mut node) => {
|
|
157
|
-
let children = &mut node.1;
|
|
158
|
-
let mut found = false;
|
|
159
|
-
let mut index = 0;
|
|
160
|
-
|
|
161
|
-
for (i, child) in children.iter().enumerate() {
|
|
162
|
-
let child_reader = child.read().await;
|
|
163
|
-
match &child_reader.node_type {
|
|
164
|
-
NodeType::File(child_file_path) => {
|
|
165
|
-
// TODO(sualeh): THERE HAS TO BE A BETTER WAY TO DO THIS.
|
|
166
|
-
if child_file_path == &file_path {
|
|
167
|
-
found = true;
|
|
168
|
-
index = i;
|
|
169
|
-
break;
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
NodeType::Branch(_) => {
|
|
173
|
-
continue;
|
|
174
|
-
}
|
|
175
|
-
NodeType::ErrorNode(_) => {
|
|
176
|
-
continue;
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
if found {
|
|
182
|
-
// remove the child from the parent.
|
|
183
|
-
let _ = children.remove(index);
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
NodeType::File(_) => {
|
|
187
|
-
return Err(anyhow::anyhow!(
|
|
188
|
-
"delete_file: This should not happen! parent was a file ..."
|
|
189
|
-
));
|
|
190
|
-
}
|
|
191
|
-
NodeType::ErrorNode(_) => {
|
|
192
|
-
return Err(anyhow::anyhow!(
|
|
193
|
-
"delete_file: This should not happen! parent was an error node ..."
|
|
194
|
-
));
|
|
195
|
-
}
|
|
196
|
-
};
|
|
197
|
-
|
|
198
|
-
// need to propogate the change up the tree.
|
|
199
|
-
mut_parent.update_hash_of_ancestor_path();
|
|
200
|
-
|
|
201
|
-
// Remove the file from the files map
|
|
202
|
-
self.files.remove(&file_path);
|
|
203
|
-
|
|
204
|
-
Ok(())
|
|
205
|
-
}
|
|
206
|
-
}
|