@anysphere/file-service 0.0.0-b4c871b2 → 0.0.0-bf8eca2b

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.
@@ -1,9 +1,13 @@
1
+ use crate::git_utils;
2
+
1
3
  use super::file_utils;
2
4
  use sha2::Digest;
5
+ use std::collections::{BTreeMap, HashSet};
3
6
  use std::path::PathBuf;
4
- use std::{collections::HashMap, fs, path::Path, sync::Arc};
7
+ use std::{fs, path::Path, sync::Arc};
5
8
  use tokio::sync::RwLock;
6
9
  use tonic::async_trait;
10
+ use tracing::info;
7
11
  pub mod local_construction;
8
12
  pub mod test;
9
13
 
@@ -12,7 +16,9 @@ pub type MerkleNodePtr = Arc<RwLock<MerkleNode>>;
12
16
  pub struct MerkleTree {
13
17
  root_path: String,
14
18
  root: MerkleNodePtr,
15
- files: HashMap<String, File>,
19
+ files: BTreeMap<String, File>,
20
+ cursor: Option<usize>,
21
+ git_ignored_files: HashSet<String>,
16
22
  }
17
23
 
18
24
  #[derive(Debug)]
@@ -50,12 +56,19 @@ fn get_id() -> i32 {
50
56
 
51
57
  #[async_trait]
52
58
  pub trait LocalConstruction {
53
- async fn new(root_directory: Option<String>) -> Result<MerkleTree, anyhow::Error>;
54
- async fn construct_merkle_tree(root_directory: String) -> Result<MerkleTree, anyhow::Error>;
59
+ async fn new(
60
+ root_directory: Option<String>,
61
+ ) -> Result<MerkleTree, anyhow::Error>;
62
+
63
+ async fn construct_merkle_tree(
64
+ root_directory: String,
65
+ ) -> Result<MerkleTree, anyhow::Error>;
66
+
55
67
  async fn update_file(
56
68
  &mut self,
57
69
  file_path: String,
58
70
  ) -> Result<(), anyhow::Error>;
71
+
59
72
  async fn delete_file(
60
73
  &mut self,
61
74
  file_path: String,
@@ -79,96 +92,267 @@ impl MerkleTree {
79
92
  pub fn empty_tree() -> MerkleTree {
80
93
  MerkleTree {
81
94
  root: Arc::new(RwLock::new(MerkleNode::empty_node(None, None))),
82
- files: HashMap::new(),
95
+ files: BTreeMap::new(),
83
96
  root_path: "".to_string(),
97
+ cursor: None,
98
+ git_ignored_files: HashSet::new(),
99
+ }
100
+ }
101
+
102
+ pub async fn get_subtree_hash(
103
+ &self,
104
+ absolute_path: PathBuf,
105
+ ) -> Result<String, anyhow::Error> {
106
+ let abs_string = match absolute_path.to_str() {
107
+ Some(s) => s.to_string(),
108
+ None => {
109
+ return Err(anyhow::anyhow!(
110
+ "get_subtree_hash: Failed to convert path to string"
111
+ ))
112
+ }
113
+ };
114
+
115
+ let node = match self.files.get(&abs_string) {
116
+ Some(file) => file.node.clone(),
117
+ None => {
118
+ return Err(anyhow::anyhow!("Could not find file in tree!"));
119
+ }
120
+ };
121
+
122
+ let node_reader = node.read().await;
123
+ let node_hash = node_reader.hash.clone();
124
+
125
+ Ok(node_hash)
126
+ }
127
+
128
+ pub async fn get_num_embeddable_files(&self) -> Result<i32, anyhow::Error> {
129
+ let mut count = 0;
130
+
131
+ for (_, file) in &self.files {
132
+ let file_reader = file.node.read().await;
133
+ match &file_reader.node_type {
134
+ NodeType::File(_) => {
135
+ count += 1;
136
+ }
137
+ NodeType::Branch(_) => {
138
+ continue;
139
+ }
140
+ NodeType::ErrorNode(_) => {
141
+ continue;
142
+ }
143
+ }
144
+ }
145
+
146
+ Ok(count)
147
+ }
148
+
149
+ pub async fn get_num_embeddable_files_in_subtree(
150
+ &self,
151
+ absolute_path: PathBuf,
152
+ ) -> Result<i32, anyhow::Error> {
153
+ let mut count = 0;
154
+
155
+ let absolute_path = match absolute_path.to_str() {
156
+ Some(s) => s.to_string(),
157
+ None => {
158
+ return Err(anyhow::anyhow!(
159
+ "get_num_embeddable_files_in_subtree: Failed to convert path to string"
160
+ ))
161
+ }
162
+ };
163
+
164
+ // TODO(sualeh): worth keeping this list sorted. its now a btree
165
+
166
+ for (_, file) in &self.files {
167
+ let file_reader = file.node.read().await;
168
+ match &file_reader.node_type {
169
+ NodeType::File(file_name) => {
170
+ if file_name.contains(&absolute_path) {
171
+ count += 1;
172
+ }
173
+ }
174
+ NodeType::Branch(_) => {
175
+ continue;
176
+ }
177
+ NodeType::ErrorNode(_) => {
178
+ continue;
179
+ }
180
+ }
181
+ }
182
+
183
+ Ok(count)
184
+ }
185
+
186
+ pub async fn get_all_files(&self) -> Result<Vec<String>, anyhow::Error> {
187
+ let mut files = Vec::new();
188
+
189
+ for (file_name, file) in &self.files {
190
+ let file_reader = file.node.read().await;
191
+ match &file_reader.node_type {
192
+ NodeType::File(_) => {
193
+ files.push(file_name.clone());
194
+ }
195
+ NodeType::Branch(_) => {
196
+ continue;
197
+ }
198
+ NodeType::ErrorNode(_) => {
199
+ continue;
200
+ }
201
+ }
202
+ }
203
+
204
+ Ok(files)
205
+ }
206
+
207
+ pub async fn get_hashes_for_files(
208
+ &self,
209
+ files: Vec<String>,
210
+ ) -> Result<Vec<String>, anyhow::Error> {
211
+ let mut hashes = Vec::new();
212
+
213
+ for file_name in files {
214
+ let file = match self.files.get(&file_name) {
215
+ Some(file) => file,
216
+ None => {
217
+ return Err(anyhow::anyhow!("Could not find file in tree!"));
218
+ }
219
+ };
220
+
221
+ let file_reader = file.node.read().await;
222
+ match &file_reader.node_type {
223
+ NodeType::File(_) => {
224
+ hashes.push(file_reader.hash.clone());
225
+ }
226
+ NodeType::Branch(_) => {
227
+ continue;
228
+ }
229
+ NodeType::ErrorNode(_) => {
230
+ continue;
231
+ }
232
+ }
233
+ }
234
+
235
+ Ok(hashes)
236
+ }
237
+
238
+ /// Returns a filename, and then a path from its parent to the root (which can possibly be empty.)
239
+ pub async fn get_next_file_to_embed(
240
+ &mut self,
241
+ ) -> Result<(String, Vec<String>), anyhow::Error> {
242
+ // if the cursor is none, set it to 0
243
+ let cursor = match self.cursor {
244
+ Some(cursor) => cursor,
245
+ None => {
246
+ self.cursor = Some(0);
247
+ 0
248
+ }
249
+ };
250
+
251
+ // get the thing at the cursor. while we dont find a file, we keep incrementing the cursor.
252
+ let mut cursor = cursor;
253
+ loop {
254
+ // O(log n)
255
+ let file = match self.files.values().nth(cursor) {
256
+ Some(file) => file,
257
+ None => {
258
+ return Err(anyhow::anyhow!("Could not find file to embed!"));
259
+ }
260
+ };
261
+
262
+ let file_reader = file.node.read().await;
263
+ match &file_reader.node_type {
264
+ NodeType::File(f) => {
265
+ // update the cursor.
266
+ self.cursor = Some(cursor + 1);
267
+ let spline = self.get_spline(f).await?;
268
+ return Ok((f.clone(), spline));
269
+ }
270
+ NodeType::Branch(_) => {
271
+ cursor += 1;
272
+ continue;
273
+ }
274
+ NodeType::ErrorNode(_) => {
275
+ cursor += 1;
276
+ continue;
277
+ }
278
+ }
279
+ }
280
+ }
281
+
282
+ pub async fn get_all_dir_files_to_embed(
283
+ &self,
284
+ absolute_path: &str,
285
+ ) -> Result<Vec<String>, anyhow::Error> {
286
+ let mut files = Vec::new();
287
+
288
+ for (file_path, f) in &self.files {
289
+ if !file_path.contains(absolute_path) {
290
+ continue;
291
+ }
292
+
293
+ match f.node.read().await.node_type {
294
+ NodeType::File(_) => {
295
+ files.push(file_path.clone());
296
+ }
297
+ NodeType::Branch(_) => {
298
+ continue;
299
+ }
300
+ NodeType::ErrorNode(_) => {
301
+ continue;
302
+ }
303
+ }
84
304
  }
305
+
306
+ Ok(files)
85
307
  }
86
308
 
87
- pub async fn get_subtree_hash(&self, path: String) -> Result<String, anyhow::Error> {
88
- let path = PathBuf::from(path);
89
- let node = match self.files.get(path.to_str().unwrap()) {
90
- Some(file) => file.node.clone(),
91
- None => {
92
- return Err(anyhow::anyhow!("Could not find file in tree!"));
93
- }
94
- };
95
-
96
- let node_reader = node.read().await;
97
- let node_hash = node_reader.hash.clone();
98
-
99
- Ok(node_hash)
100
- }
101
-
102
- pub async fn get_num_embeddable_files(&self) -> Result<i32, anyhow::Error> {
103
- let mut count = 0;
104
-
105
- for (_, file) in &self.files {
106
- let file_reader = file.node.read().await;
107
- match &file_reader.node_type {
108
- NodeType::File(_) => {
109
- count += 1;
110
- }
111
- NodeType::Branch(_) => {
112
- continue;
113
- }
114
- NodeType::ErrorNode(_) => {
115
- continue;
116
- }
117
- }
118
- }
119
-
120
- Ok(count)
121
- }
122
-
123
- pub async fn get_all_files(&self) -> Result<Vec<String>, anyhow::Error> {
124
- let mut files = Vec::new();
125
-
126
- for (file_name, file) in &self.files {
127
- let file_reader = file.node.read().await;
128
- match &file_reader.node_type {
129
- NodeType::File(_) => {
130
- files.push(file_name.clone());
131
- }
132
- NodeType::Branch(_) => {
133
- continue;
134
- }
135
- NodeType::ErrorNode(_) => {
136
- continue;
137
- }
138
- }
139
- }
140
-
141
- Ok(files)
142
- }
143
-
144
- pub async fn get_hashes_for_files(&self, files: Vec<String>) -> Result<Vec<String>, anyhow::Error> {
145
- let mut hashes = Vec::new();
146
-
147
- for file_name in files {
148
- let file = match self.files.get(&file_name) {
149
- Some(file) => file,
150
- None => {
151
- return Err(anyhow::anyhow!("Could not find file in tree!"));
152
- }
153
- };
154
-
155
- let file_reader = file.node.read().await;
156
- match &file_reader.node_type {
157
- NodeType::File(_) => {
158
- hashes.push(file_reader.hash.clone());
159
- }
160
- NodeType::Branch(_) => {
161
- continue;
162
- }
163
- NodeType::ErrorNode(_) => {
164
- continue;
165
- }
166
- }
167
- }
168
-
169
- Ok(hashes)
170
- }
309
+ // TODO(sualeh): i need tests for this!!
310
+ pub async fn get_spline(
311
+ &self,
312
+ absolute_path: &str,
313
+ ) -> Result<Vec<String>, anyhow::Error> {
314
+ info!("get_spline called with absolute_path: {}", absolute_path);
315
+ let mut files = Vec::new();
316
+
317
+ let current_node = match self.files.get(absolute_path) {
318
+ Some(node) => {
319
+ info!("Found node for absolute_path: {}", absolute_path);
320
+ node.node.clone()
321
+ }
322
+ None => {
323
+ info!("File not found for absolute_path: {}", absolute_path);
324
+ return Err(anyhow::anyhow!("File not found: {}", absolute_path));
325
+ }
326
+ };
327
+
328
+ let mut stack = Vec::new();
329
+ stack.push(current_node);
330
+
331
+ while let Some(node) = stack.pop() {
332
+ let parent = node.read().await.parent.clone();
333
+ if let Some(parent) = parent {
334
+ info!("Adding parent hash to files vector");
335
+ {
336
+ let parent_node = parent.read().await;
337
+ match &parent_node.node_type {
338
+ NodeType::File(file_name) => {
339
+ files.push(file_name.clone());
340
+ }
341
+ NodeType::Branch((branch_name, _)) => {
342
+ files.push(branch_name.clone());
343
+ }
344
+ _ => {
345
+ continue;
346
+ }
347
+ }
348
+ }
171
349
 
350
+ stack.push(parent);
351
+ }
352
+ }
353
+ info!("Returning files vector with {} elements", files.len());
354
+ Ok(files)
355
+ }
172
356
 
173
357
  /// creates a new node and attaches it to the current tree.
174
358
  /// SPEC:
@@ -205,12 +389,18 @@ impl MerkleTree {
205
389
  // 1. the path is empty. this means that the ancestor is the root.
206
390
  // 2. the path is non-empty. that means there exist a non-empty element btwn till the root.
207
391
 
392
+ let absolute_root_path = self.root_path.clone();
208
393
  let new_node = match path.len() {
209
394
  0 => {
210
395
  // this means that the ancestor is the root.
211
396
  // we need to create a new node and attach it to the ancestor.
212
- let new_node =
213
- MerkleNode::new(file_path.clone(), Some(ancestor.clone())).await;
397
+ let new_node = MerkleNode::new(
398
+ file_path.clone(),
399
+ Some(ancestor.clone()),
400
+ &self.git_ignored_files,
401
+ &absolute_root_path.as_str(),
402
+ )
403
+ .await;
214
404
  ancestor.write().await.attach_child(new_node.clone()).await;
215
405
  new_node
216
406
  }
@@ -221,9 +411,13 @@ impl MerkleTree {
221
411
  // UNSURE: not sure this is the correct thing to do but it is the fastest.
222
412
  // get the last thing that is not in the tree.
223
413
  let first_child_path = path.last().unwrap();
224
- let first_child =
225
- MerkleNode::new(first_child_path.clone(), Some(ancestor.clone()))
226
- .await;
414
+ let first_child = MerkleNode::new(
415
+ first_child_path.clone(),
416
+ Some(ancestor.clone()),
417
+ &self.git_ignored_files,
418
+ &absolute_root_path.as_str(),
419
+ )
420
+ .await;
227
421
 
228
422
  // TODO(sualeh): we should do an assertion check that the entire vec is contained here.
229
423
 
@@ -234,7 +428,7 @@ impl MerkleTree {
234
428
  }
235
429
  };
236
430
 
237
- Ok(new_node)
431
+ Ok(new_node)
238
432
  }
239
433
 
240
434
  /// Spec:
@@ -298,17 +492,21 @@ impl MerkleTree {
298
492
  /// - attaches to the ancestor.
299
493
  /// - adds to the filemap
300
494
  /// - updates hashes of ancestor path.
301
- async fn attach_new_node_to_tree(&mut self, file_path: String) -> Result<(), anyhow::Error> {
495
+ async fn attach_new_node_to_tree(
496
+ &mut self,
497
+ file_path: String,
498
+ ) -> Result<(), anyhow::Error> {
302
499
  let path = PathBuf::from(file_path.clone());
303
500
  match self.create_new_node_and_attach_to_ancestors(path).await {
304
- Ok(node_ptr) => {
305
- self.add_subtree_to_filemap(node_ptr).await;
306
- Ok(())
307
- }
308
- Err(e) => {
309
- Err(anyhow::anyhow!("Could not create new node and attach to ancestors! {}", e.to_string()))
310
- }
311
- }
501
+ Ok(node_ptr) => {
502
+ self.add_subtree_to_filemap(node_ptr).await;
503
+ Ok(())
504
+ }
505
+ Err(e) => Err(anyhow::anyhow!(
506
+ "Could not create new node and attach to ancestors! {}",
507
+ e.to_string()
508
+ )),
509
+ }
312
510
  }
313
511
 
314
512
  /// MUTATES MUTATES MUTATES
@@ -389,20 +587,22 @@ impl MerkleTree {
389
587
  .create_new_node_and_attach_to_ancestors(file_path)
390
588
  .await;
391
589
 
392
- match node_ptr {
393
- Ok(node_ptr) => {
394
-
395
- self.files.insert(
396
- file_string,
397
- File {
398
- node: node_ptr.clone(),
399
- },
400
- );
401
- }
402
- Err(e) => {
403
- return Err(anyhow::anyhow!("Could not create new node and attach to ancestors! {}", e.to_string()));
404
- }
405
- }
590
+ match node_ptr {
591
+ Ok(node_ptr) => {
592
+ self.files.insert(
593
+ file_string,
594
+ File {
595
+ node: node_ptr.clone(),
596
+ },
597
+ );
598
+ }
599
+ Err(e) => {
600
+ return Err(anyhow::anyhow!(
601
+ "Could not create new node and attach to ancestors! {}",
602
+ e.to_string()
603
+ ));
604
+ }
605
+ }
406
606
 
407
607
  Ok(())
408
608
  }
@@ -494,18 +694,62 @@ use std::future::Future;
494
694
  use std::pin::Pin;
495
695
 
496
696
  type PinnedFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>;
697
+ type IgnoredFiles = HashSet<String>;
497
698
 
498
699
  impl MerkleNode {
499
700
  /// please be careful using this.
500
701
  async fn __new_unchecked(
501
702
  file_or_directory: String,
502
703
  parent: ParentPtr,
704
+ ignored_files: &IgnoredFiles,
705
+ absolute_root_path: &str,
503
706
  ) -> MerkleNodePtr {
504
- MerkleNode::construct_node(Path::new(&file_or_directory), parent).await
707
+ // check if the root is a git directory.
708
+ let is_git_repo =
709
+ match git_utils::is_git_directory(absolute_root_path).await {
710
+ Ok(is_git_repo) => is_git_repo,
711
+ Err(e) => false,
712
+ };
713
+ let bypass_git = !is_git_repo;
714
+
715
+ MerkleNode::construct_node(
716
+ Path::new(&file_or_directory),
717
+ parent,
718
+ ignored_files,
719
+ absolute_root_path,
720
+ bypass_git,
721
+ )
722
+ .await
505
723
  }
506
724
 
507
- async fn new(file_or_directory: PathBuf, parent: ParentPtr) -> MerkleNodePtr {
508
- MerkleNode::construct_node(Path::new(&file_or_directory), parent).await
725
+ async fn new(
726
+ absolute_file_or_directory: PathBuf,
727
+ parent: ParentPtr,
728
+ ignored_files: &IgnoredFiles,
729
+ absolute_root_path: &str,
730
+ ) -> MerkleNodePtr {
731
+ // check if the root is a git directory.
732
+ let is_git_repo =
733
+ match git_utils::is_git_directory(absolute_root_path).await {
734
+ Ok(is_git_repo) => is_git_repo,
735
+ Err(_e) => false,
736
+ };
737
+ let bypass_git = !is_git_repo;
738
+
739
+ info!(
740
+ "constructing node for absolute_file_or_directory: {:?}",
741
+ absolute_file_or_directory
742
+ );
743
+ info!("bypass_git: {}, is_git_repo: {}", bypass_git, is_git_repo);
744
+
745
+ MerkleNode::construct_node(
746
+ Path::new(&absolute_file_or_directory),
747
+ parent,
748
+ ignored_files,
749
+ absolute_root_path,
750
+ bypass_git,
751
+ )
752
+ .await
509
753
  }
510
754
 
511
755
  /// NOT added to the tree by default.
@@ -516,38 +760,64 @@ impl MerkleNode {
516
760
  // let file_hash = self.files.get_mut(&file_path).unwrap();
517
761
 
518
762
  fn construct_node<'a>(
519
- file_or_directory: &'a Path,
763
+ absolute_file_or_directory: &'a Path,
520
764
  parent: ParentPtr,
765
+ ignored_files: &'a IgnoredFiles,
766
+ absolute_root_path: &'a str,
767
+ bypass_git: bool,
521
768
  ) -> PinnedFuture<'a, MerkleNodePtr> {
522
769
  Box::pin(async move {
523
770
  // check if it is a file
524
- let path_str = file_or_directory.to_str().unwrap().to_string();
525
- if file_or_directory.is_file() {
771
+ let path_str = absolute_file_or_directory.to_str().unwrap().to_string();
772
+ if absolute_file_or_directory.is_file() {
526
773
  return Arc::new(RwLock::new(
527
774
  MerkleNode::construct_file_node_or_error_node(
528
- file_or_directory,
775
+ absolute_file_or_directory,
529
776
  parent,
777
+ ignored_files,
530
778
  )
531
779
  .await,
532
780
  ));
533
781
  }
534
782
 
535
- // check if the directory fails the bad dir test.
536
- let is_bad_dir = file_utils::is_in_bad_dir(file_or_directory);
537
- if is_bad_dir.is_err() || is_bad_dir.unwrap_or(false) {
538
- // println!("skipping directory: {}", path_str);
539
- return Arc::new(RwLock::new(MerkleNode::empty_node(
540
- Some(file_or_directory),
541
- Some("Directory is in bad dir!".to_string()),
542
- )));
543
- }
783
+ // check if the directory fails the bad dir test.
784
+ let is_bad_dir = file_utils::is_in_bad_dir(absolute_file_or_directory);
785
+ if is_bad_dir.is_err() || is_bad_dir.unwrap_or(false) {
786
+ // println!("skipping directory: {}", path_str);
787
+ return Arc::new(RwLock::new(MerkleNode::empty_node(
788
+ Some(absolute_file_or_directory),
789
+ Some("Directory is in bad dir!".to_string()),
790
+ )));
791
+ }
544
792
 
545
- let entries = fs::read_dir(file_or_directory);
793
+ // check if the directory is git ignored
794
+ let is_git_ignored =
795
+ match git_utils::is_git_ignored(absolute_root_path, path_str.as_str())
796
+ .await
797
+ {
798
+ Ok(is_git_ignored) => is_git_ignored,
799
+ Err(e) => {
800
+ return Arc::new(RwLock::new(MerkleNode::empty_node(
801
+ Some(absolute_file_or_directory),
802
+ Some(e.to_string()),
803
+ )));
804
+ }
805
+ };
806
+
807
+ if is_git_ignored && !bypass_git {
808
+ // println!("skipping directory: {}", path_str);
809
+ return Arc::new(RwLock::new(MerkleNode::empty_node(
810
+ Some(absolute_file_or_directory),
811
+ Some("Directory is git ignored!".to_string()),
812
+ )));
813
+ }
814
+
815
+ let entries = fs::read_dir(absolute_file_or_directory);
546
816
  match entries {
547
817
  Ok(_) => (),
548
818
  Err(e) => {
549
819
  return Arc::new(RwLock::new(MerkleNode::empty_node(
550
- Some(file_or_directory),
820
+ Some(absolute_file_or_directory),
551
821
  Some(e.to_string()),
552
822
  )));
553
823
  }
@@ -567,13 +837,19 @@ impl MerkleNode {
567
837
  match entry {
568
838
  Ok(entry) => {
569
839
  children.push(
570
- MerkleNode::construct_node(&entry.path(), Some(node.clone()))
571
- .await,
840
+ MerkleNode::construct_node(
841
+ &entry.path(),
842
+ Some(node.clone()),
843
+ ignored_files,
844
+ absolute_root_path,
845
+ bypass_git,
846
+ )
847
+ .await,
572
848
  );
573
849
  }
574
850
  Err(e) => {
575
851
  children.push(Arc::new(RwLock::new(MerkleNode::empty_node(
576
- Some(file_or_directory),
852
+ Some(absolute_file_or_directory),
577
853
  Some(e.to_string()),
578
854
  ))));
579
855
  }
@@ -593,23 +869,33 @@ impl MerkleNode {
593
869
  }
594
870
 
595
871
  async fn construct_file_node(
596
- file_path: &Path,
872
+ absolute_file_path: &Path,
597
873
  parent: ParentPtr,
874
+ ignored_files: &IgnoredFiles,
598
875
  ) -> Result<MerkleNode, String> {
599
- let file_str = file_path
876
+ let file_str = absolute_file_path
600
877
  .to_str()
601
878
  .ok_or("Could not convert file path to string!")?
602
879
  .to_string();
603
880
  // first see if it passes the
604
- match file_utils::is_good_file(file_path) {
881
+ match file_utils::is_good_file(absolute_file_path) {
605
882
  Ok(_) => {}
606
883
  Err(e) => {
607
884
  return Err(format!("File failed runtime checks! {}", e.to_string()));
608
885
  }
609
886
  }
610
887
 
888
+ // check if the file is in the git ignore buffer.
889
+ // this is a bug right because we are not checking absoluteness here.
890
+ match ignored_files.contains(&file_str) {
891
+ true => {
892
+ return Err(format!("File is in git ignore buffer!"));
893
+ }
894
+ false => {}
895
+ }
896
+
611
897
  // read the file_content to a buffer
612
- let file_content = match tokio::fs::read(file_path).await {
898
+ let file_content = match tokio::fs::read(absolute_file_path).await {
613
899
  Ok(content) => content,
614
900
  Err(e) => {
615
901
  return Err(format!("Could not read file! {}", e.to_string()));
@@ -617,7 +903,11 @@ impl MerkleNode {
617
903
  };
618
904
 
619
905
  // check if the file passes runtime checks.
620
- match file_utils::is_good_file_runtime_check(file_path, &file_content).await
906
+ match file_utils::is_good_file_runtime_check(
907
+ absolute_file_path,
908
+ &file_content,
909
+ )
910
+ .await
621
911
  {
622
912
  Ok(_) => {}
623
913
  Err(e) => {
@@ -648,15 +938,22 @@ impl MerkleNode {
648
938
  }
649
939
 
650
940
  async fn construct_file_node_or_error_node(
651
- file_path: &Path,
941
+ absolute_file_path: &Path,
652
942
  parent: ParentPtr,
943
+ ignored_files: &IgnoredFiles,
653
944
  ) -> MerkleNode {
654
- let node = match MerkleNode::construct_file_node(file_path, parent).await {
945
+ let node = match MerkleNode::construct_file_node(
946
+ absolute_file_path,
947
+ parent,
948
+ ignored_files,
949
+ )
950
+ .await
951
+ {
655
952
  Ok(node) => node,
656
953
  Err(e) => {
657
954
  // println!("constructing error node. error: {}", e);
658
- // println!("file_path: {:?}", file_path);
659
- MerkleNode::empty_node(Some(file_path), Some(e))
955
+ // println!("file_path: {:?}", file_path);
956
+ MerkleNode::empty_node(Some(absolute_file_path), Some(e))
660
957
  }
661
958
  };
662
959