@anysphere/file-service 0.0.0-dacf38fa → 0.0.0-e0c70bcd

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