@anysphere/file-service 0.0.0-fcf7dd4f → 0.0.0-fd010bd5

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/Cargo.toml CHANGED
@@ -6,6 +6,10 @@ version = "0.0.0"
6
6
  [lib]
7
7
  crate-type = ["cdylib"]
8
8
 
9
+ [features]
10
+ default = ["windows-subsystem"]
11
+ windows-subsystem = []
12
+
9
13
  [dependencies]
10
14
  # Default enable napi4 feature, see https://nodejs.org/api/n-api.html#node-api-version-matrix
11
15
  napi = { version = "2.12.2", default-features = false, features = ["napi4", "async", "tokio_rt"] }
@@ -22,6 +26,7 @@ tracing-subscriber = "0.3.17"
22
26
  tracing-appender = "0.2.2"
23
27
  binaryornot = "1.0.0"
24
28
  dunce = "1.0.1"
29
+ encoding_rs = "0.8.33"
25
30
 
26
31
  [build-dependencies]
27
32
  napi-build = "2.0.1"
@@ -29,5 +34,6 @@ tonic-build = "0.9.2"
29
34
  anyhow = "1.0.75"
30
35
  glob = "0.3.0"
31
36
 
37
+
32
38
  [profile.release]
33
39
  lto = true
package/build.rs CHANGED
@@ -3,6 +3,8 @@ use std::path::Path;
3
3
  extern crate napi_build;
4
4
 
5
5
  fn main() -> Result<(), anyhow::Error> {
6
+ #[cfg(target_os = "windows")]
7
+ println!("cargo:rustc-cdylib-link-arg=/SUBSYSTEM:WINDOWS");
6
8
  napi_build::setup();
7
9
 
8
10
  // print the relative path.
package/index.d.ts CHANGED
@@ -5,8 +5,8 @@
5
5
 
6
6
  export class MerkleClient {
7
7
  constructor(absoluteRootDirectory: string)
8
- init(): Promise<void>
9
- computeMerkleTree(): Promise<void>
8
+ init(gitIgnoredFiles: Array<string>, isGitRepo: boolean): Promise<void>
9
+ computeMerkleTree(gitIgnoredFiles: Array<string>, isGitRepo: boolean): Promise<void>
10
10
  updateFile(filePath: string): Promise<void>
11
11
  deleteFile(filePath: string): Promise<void>
12
12
  getSubtreeHash(relativePath: string): Promise<string>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@anysphere/file-service",
3
- "version": "0.0.0-fcf7dd4f",
3
+ "version": "0.0.0-fd010bd5",
4
4
  "main": "index.js",
5
5
  "types": "index.d.ts",
6
6
  "napi": {
@@ -36,12 +36,12 @@
36
36
  "version": "napi version"
37
37
  },
38
38
  "optionalDependencies": {
39
- "@anysphere/file-service-win32-x64-msvc": "0.0.0-fcf7dd4f",
40
- "@anysphere/file-service-darwin-x64": "0.0.0-fcf7dd4f",
41
- "@anysphere/file-service-linux-x64-gnu": "0.0.0-fcf7dd4f",
42
- "@anysphere/file-service-darwin-arm64": "0.0.0-fcf7dd4f",
43
- "@anysphere/file-service-win32-arm64-msvc": "0.0.0-fcf7dd4f",
44
- "@anysphere/file-service-darwin-universal": "0.0.0-fcf7dd4f",
45
- "@anysphere/file-service-linux-arm64-gnu": "0.0.0-fcf7dd4f"
39
+ "@anysphere/file-service-win32-x64-msvc": "0.0.0-fd010bd5",
40
+ "@anysphere/file-service-darwin-x64": "0.0.0-fd010bd5",
41
+ "@anysphere/file-service-linux-x64-gnu": "0.0.0-fd010bd5",
42
+ "@anysphere/file-service-darwin-arm64": "0.0.0-fd010bd5",
43
+ "@anysphere/file-service-win32-arm64-msvc": "0.0.0-fd010bd5",
44
+ "@anysphere/file-service-darwin-universal": "0.0.0-fd010bd5",
45
+ "@anysphere/file-service-linux-arm64-gnu": "0.0.0-fd010bd5"
46
46
  }
47
47
  }
package/src/file_utils.rs CHANGED
@@ -5,6 +5,7 @@
5
5
  // 4. vscode.fs.stat
6
6
 
7
7
  use anyhow::Error;
8
+ use encoding_rs::UTF_8;
8
9
  use std::path::Path;
9
10
  use tokio::fs;
10
11
 
@@ -43,8 +44,90 @@ pub fn is_good_file(file_path: &Path) -> Result<(), Error> {
43
44
  _ => {}
44
45
  }
45
46
 
46
- match extension {
47
- "lock" | "bak" | "tmp" | "bin" | "exe" | "dll" | "so" | "lockb" => {
47
+ let bad_extensions = vec![
48
+ "lock",
49
+ "bak",
50
+ "tmp",
51
+ "bin",
52
+ "exe",
53
+ "dll",
54
+ "so",
55
+ "lockb",
56
+ "qwoff",
57
+ "isl",
58
+ "csv",
59
+ "pdf",
60
+ // add ms word, excel, powerpoint, etc.
61
+ "doc",
62
+ "docx",
63
+ "xls",
64
+ "xlsx",
65
+ "ppt",
66
+ "pptx",
67
+ "odt",
68
+ "ods",
69
+ "odp",
70
+ "odg",
71
+ "odf",
72
+ "sxw",
73
+ "sxc",
74
+ "sxi",
75
+ "sxd",
76
+ "sdc",
77
+ // add images
78
+ "jpg",
79
+ "jpeg",
80
+ "png",
81
+ "gif",
82
+ "bmp",
83
+ "tif",
84
+ // add audio
85
+ "mp3",
86
+ "wav",
87
+ "wma",
88
+ "ogg",
89
+ "flac",
90
+ "aac",
91
+ // add video
92
+ "mp4",
93
+ "mov",
94
+ "wmv",
95
+ "flv",
96
+ "avi",
97
+ // add archives
98
+ "zip",
99
+ "tar",
100
+ "gz",
101
+ "7z",
102
+ "rar",
103
+ "tgz",
104
+ "dmg",
105
+ "iso",
106
+ "cue",
107
+ "mdf",
108
+ "mds",
109
+ "vcd",
110
+ "toast",
111
+ "img",
112
+ "apk",
113
+ "msi",
114
+ "cab",
115
+ "tar.gz",
116
+ "tar.xz",
117
+ "tar.bz2",
118
+ "tar.lzma",
119
+ "tar.Z",
120
+ "tar.sz",
121
+ "lzma",
122
+ // add fonts
123
+ "ttf",
124
+ "otf",
125
+ "woff",
126
+ "woff2",
127
+ "eot",
128
+ ];
129
+ match bad_extensions.contains(&extension) {
130
+ true => {
48
131
  return Err(anyhow::anyhow!("File is just a lock file"));
49
132
  }
50
133
  _ => {}
@@ -93,7 +176,7 @@ pub fn is_good_file(file_path: &Path) -> Result<(), Error> {
93
176
  // implement the buffer above:
94
177
  pub async fn is_good_file_runtime_check(
95
178
  file_path: &Path,
96
- _buffer: &[u8],
179
+ // _buffer: &[u8],
97
180
  ) -> Result<(), Error> {
98
181
  match get_file_size(file_path).await {
99
182
  Ok(size) if size > 2 * 1024 * 1024 => {
@@ -103,13 +186,31 @@ pub async fn is_good_file_runtime_check(
103
186
  _ => {}
104
187
  }
105
188
 
106
- // if is_binary(file_path).context("Failed to check if file is binary")? {
107
- // return Err(anyhow::anyhow!("File is binary"));
108
- // }
189
+ // if is_binary(file_path).context("Failed to check if file is binary")? {
190
+ // return Err(anyhow::anyhow!("File is binary"));
191
+ // }
109
192
 
110
193
  Ok(())
111
194
  }
112
195
 
196
+ pub async fn read_string_without_bom(
197
+ file_path: &Path,
198
+ ) -> Result<String, Error> {
199
+ let file_buffer = match fs::read(file_path).await {
200
+ Ok(buffer) => buffer,
201
+ Err(e) => {
202
+ return Err(anyhow::anyhow!(
203
+ "Failed to read file buffer: {}",
204
+ e.to_string()
205
+ ))
206
+ }
207
+ };
208
+
209
+ let (cow, _) = UTF_8.decode_with_bom_removal(&file_buffer);
210
+
211
+ Ok(cow.to_string())
212
+ }
213
+
113
214
  pub fn as_relative_path(
114
215
  base_path: &Path,
115
216
  file_path: &Path,
@@ -167,25 +268,40 @@ mod tests {
167
268
  temp_file.write_all(b"Hello, world!").await.unwrap();
168
269
  let buffer = fs::read(&temp_file_path).await.unwrap();
169
270
  assert_eq!(
170
- is_good_file_runtime_check(&temp_file_path, &buffer)
171
- .await
172
- .is_ok(),
271
+ is_good_file_runtime_check(&temp_file_path).await.is_ok(),
173
272
  true
174
273
  );
175
274
  temp_dir.close().unwrap();
176
275
 
276
+ // let temp_dir = tempfile::tempdir().unwrap();
277
+ // let temp_file_path = temp_dir.path().join("test_file");
278
+ // let mut temp_file = fs::File::create(&temp_file_path).await.unwrap();
279
+ // temp_file.write_all(&[0, 159, 146, 150]).await.unwrap(); // Invalid UTF-8 sequence
280
+ // let buffer = fs::read(&temp_file_path).await.unwrap();
281
+ // assert_eq!(
282
+ // is_good_file_runtime_check(&temp_file_path).await.is_err(),
283
+ // true
284
+ // );
285
+ // temp_dir.close().unwrap();
286
+ }
287
+
288
+ #[tokio::test]
289
+ async fn test_bom_file() {
290
+ const BOM: [u8; 3] = [0xEF, 0xBB, 0xBF];
291
+ const CONTENT: &str = "Hello, world!";
292
+
293
+ // Write this to a temp file
177
294
  let temp_dir = tempfile::tempdir().unwrap();
178
295
  let temp_file_path = temp_dir.path().join("test_file");
179
296
  let mut temp_file = fs::File::create(&temp_file_path).await.unwrap();
180
- temp_file.write_all(&[0, 159, 146, 150]).await.unwrap(); // Invalid UTF-8 sequence
181
- let buffer = fs::read(&temp_file_path).await.unwrap();
182
- assert_eq!(
183
- is_good_file_runtime_check(&temp_file_path, &buffer)
184
- .await
185
- .is_err(),
186
- true
187
- );
188
- temp_dir.close().unwrap();
297
+ temp_file.write_all(&BOM).await.unwrap();
298
+ temp_file.write_all(CONTENT.as_bytes()).await.unwrap();
299
+
300
+ // expect that we read the file with tokio as the CONTENT
301
+ let file_contents = read_string_without_bom(&temp_file_path).await.unwrap();
302
+
303
+ // Check string equality of CONTENT (&str) to file_contents (String)
304
+ assert_eq!(CONTENT, file_contents);
189
305
  }
190
306
 
191
307
  #[test]
package/src/git_utils.rs CHANGED
@@ -1,4 +1,5 @@
1
1
  use std::collections::HashSet;
2
+ use std::path::MAIN_SEPARATOR_STR;
2
3
  use std::process::Command;
3
4
 
4
5
  pub fn list_ignored_files_and_directories(
@@ -19,9 +20,7 @@ pub fn list_ignored_files_and_directories(
19
20
  ],
20
21
  // FIXME(sualeh): this is super sketchy and might totally break in like a bazillion ways. i dont like it.
21
22
  vec![
22
- "sh",
23
- "-c",
24
- "git submodule foreach --quiet 'git ls-files --others --ignored --exclude-standard --directory --no-empty-directory | sed \"s|^|$path/|\"'",
23
+ "git submodule foreach --quiet 'git -C $toplevel/$path ls-files --others --ignored --exclude-standard --directory --no-empty-directory | (while read line; do echo $path/$line; done)'",
25
24
  ],
26
25
  ];
27
26
 
@@ -36,9 +35,12 @@ pub fn list_ignored_files_and_directories(
36
35
  .lines()
37
36
  .filter(|line| !line.is_empty())
38
37
  .map(|line| {
38
+ let line = line.replace("/", MAIN_SEPARATOR_STR);
39
+
39
40
  if should_return_absolute_paths {
40
41
  let mut path = std::path::PathBuf::from(workspace_root_path);
41
- path.push(line);
42
+
43
+ path.push(line.clone());
42
44
 
43
45
  match path.canonicalize() {
44
46
  Ok(canonical_path) => {
package/src/lib.rs CHANGED
@@ -1,16 +1,16 @@
1
+ #![windows_subsystem = "windows"]
1
2
  #![deny(clippy::all)]
2
3
  #![deny(unsafe_op_in_unsafe_fn)]
3
4
  pub mod file_utils;
4
- pub mod git_utils;
5
5
  pub mod merkle_tree;
6
6
 
7
- use std::vec;
7
+ use std::{collections::HashSet, vec};
8
8
 
9
+ use anyhow::Context;
9
10
  use merkle_tree::{LocalConstruction, MerkleTree};
10
11
  use tracing::{info, Level};
11
12
  use tracing_appender::rolling::{RollingFileAppender, Rotation};
12
13
  use tracing_subscriber::fmt;
13
- use anyhow::Context;
14
14
 
15
15
  #[macro_use]
16
16
  extern crate napi_derive;
@@ -19,22 +19,27 @@ extern crate napi_derive;
19
19
  pub struct MerkleClient {
20
20
  tree: MerkleTree,
21
21
  absolute_root_directory: String,
22
- _guard: tracing_appender::non_blocking::WorkerGuard,
22
+ _guard: Option<tracing_appender::non_blocking::WorkerGuard>,
23
23
  }
24
24
 
25
- pub fn init_logger() -> tracing_appender::non_blocking::WorkerGuard {
26
- let file_appender =
27
- RollingFileAppender::new(Rotation::NEVER, "./", "rust_log.txt");
28
- let (non_blocking, _guard) = tracing_appender::non_blocking(file_appender);
29
- let subscriber = fmt::Subscriber::builder()
30
- .with_max_level(Level::TRACE)
31
- .with_writer(non_blocking)
32
- .with_ansi(false)
33
- .with_line_number(true)
34
- .finish();
35
-
36
- let _ = tracing::subscriber::set_global_default(subscriber);
37
-
25
+ pub fn init_logger() -> Option<tracing_appender::non_blocking::WorkerGuard> {
26
+ #[cfg(feature = "debugfile")]
27
+ let _guard = {
28
+ let file_appender =
29
+ RollingFileAppender::new(Rotation::NEVER, "./", "rust_log.txt");
30
+ let (non_blocking, _guard) = tracing_appender::non_blocking(file_appender);
31
+ let subscriber = fmt::Subscriber::builder()
32
+ .with_max_level(Level::TRACE)
33
+ .with_writer(non_blocking)
34
+ .with_ansi(false)
35
+ .with_line_number(true)
36
+ .finish();
37
+
38
+ let _ = tracing::subscriber::set_global_default(subscriber);
39
+ _guard
40
+ };
41
+ #[cfg(not(feature = "debugfile"))]
42
+ let _guard = { None };
38
43
  _guard
39
44
  }
40
45
 
@@ -62,13 +67,19 @@ impl MerkleClient {
62
67
  }
63
68
 
64
69
  #[napi]
65
- pub async unsafe fn init(&mut self) -> Result<(), napi::Error> {
70
+ pub async unsafe fn init(
71
+ &mut self,
72
+ git_ignored_files: Vec<String>,
73
+ is_git_repo: bool,
74
+ ) -> Result<(), napi::Error> {
66
75
  // 1. compute the merkle tree
67
76
  // 2. update the backend
68
77
  // 3. sync with the remote
69
78
  info!("Merkle tree compute started!");
70
79
  unsafe {
71
- self.compute_merkle_tree().await?;
80
+ self
81
+ .compute_merkle_tree(git_ignored_files, is_git_repo)
82
+ .await?;
72
83
  }
73
84
 
74
85
  Ok(())
@@ -81,9 +92,18 @@ impl MerkleClient {
81
92
  #[napi]
82
93
  pub async unsafe fn compute_merkle_tree(
83
94
  &mut self,
95
+ git_ignored_files: Vec<String>,
96
+ is_git_repo: bool,
84
97
  ) -> Result<(), napi::Error> {
85
- let t =
86
- MerkleTree::construct_merkle_tree(self.absolute_root_directory.clone()).await;
98
+ // make the git ignored files into a hash set
99
+ let git_ignored_set = HashSet::from_iter(git_ignored_files.into_iter());
100
+
101
+ let t = MerkleTree::construct_merkle_tree(
102
+ self.absolute_root_directory.clone(),
103
+ git_ignored_set,
104
+ is_git_repo,
105
+ )
106
+ .await;
87
107
 
88
108
  match t {
89
109
  Ok(tree) => {
@@ -112,14 +132,16 @@ impl MerkleClient {
112
132
  &self,
113
133
  relative_path: String,
114
134
  ) -> Result<String, napi::Error> {
115
-
116
- let relative_path_without_leading_slash = match relative_path.strip_prefix('.') {
135
+ let relative_path_without_leading_slash = match relative_path
136
+ .strip_prefix('.')
137
+ {
117
138
  Some(path) => path.strip_prefix(std::path::MAIN_SEPARATOR).unwrap_or(""),
118
139
  None => relative_path.as_str(),
119
140
  };
120
141
 
121
142
  let absolute_path = if !relative_path_without_leading_slash.is_empty() {
122
- std::path::Path::new(&self.absolute_root_directory).join(relative_path_without_leading_slash)
143
+ std::path::Path::new(&self.absolute_root_directory)
144
+ .join(relative_path_without_leading_slash)
123
145
  } else {
124
146
  std::path::Path::new(&self.absolute_root_directory).to_path_buf()
125
147
  };
@@ -129,12 +151,15 @@ impl MerkleClient {
129
151
  None => {
130
152
  return Err(napi::Error::new(
131
153
  napi::Status::Unknown,
132
- format!("some string error")
154
+ format!("some string error"),
133
155
  ))
134
156
  }
135
157
  };
136
158
 
137
- let hash = self.tree.get_subtree_hash(absolute_path_string.as_str()).await;
159
+ let hash = self
160
+ .tree
161
+ .get_subtree_hash(absolute_path_string.as_str())
162
+ .await;
138
163
 
139
164
  match hash {
140
165
  Ok(hash) => Ok(hash),
@@ -153,7 +178,7 @@ impl MerkleClient {
153
178
  Ok(num) => Ok(num),
154
179
  Err(e) => Err(napi::Error::new(
155
180
  napi::Status::Unknown,
156
- format!("Error in get_num_embeddable_files: {:?}", e)
181
+ format!("Error in get_num_embeddable_files: {:?}", e),
157
182
  )),
158
183
  }
159
184
  }
@@ -175,7 +200,7 @@ impl MerkleClient {
175
200
  Ok(num) => Ok(num),
176
201
  Err(e) => Err(napi::Error::new(
177
202
  napi::Status::Unknown,
178
- format!("Error in get_num_embeddable_files_in_subtree: {:?}", e)
203
+ format!("Error in get_num_embeddable_files_in_subtree: {:?}", e),
179
204
  )),
180
205
  }
181
206
  }
@@ -188,7 +213,7 @@ impl MerkleClient {
188
213
  Ok(files) => Ok(files),
189
214
  Err(e) => Err(napi::Error::new(
190
215
  napi::Status::Unknown,
191
- format!("Error in get_all_files: {:?}", e)
216
+ format!("Error in get_all_files: {:?}", e),
192
217
  )),
193
218
  }
194
219
  }
@@ -1,4 +1,3 @@
1
- use crate::git_utils;
2
1
  use crate::merkle_tree::{
3
2
  File, MerkleNode, MerkleNodePtr, NodeType, PinnedFuture,
4
3
  };
@@ -13,8 +12,13 @@ impl LocalConstruction for MerkleTree {
13
12
  async fn new(
14
13
  root_directory: Option<String>,
15
14
  ) -> Result<MerkleTree, anyhow::Error> {
15
+ let git_ignored_files = HashSet::<String>::new();
16
16
  if let Some(root_directory) = root_directory {
17
- let n = MerkleTree::construct_merkle_tree(root_directory).await;
17
+ let n = MerkleTree::construct_merkle_tree(
18
+ root_directory,
19
+ git_ignored_files,
20
+ false
21
+ ).await;
18
22
  return n;
19
23
  }
20
24
 
@@ -30,6 +34,8 @@ impl LocalConstruction for MerkleTree {
30
34
  /// 4. return merkle tree
31
35
  async fn construct_merkle_tree(
32
36
  absolute_path_to_root_directory: String,
37
+ git_ignored_files_and_dirs: HashSet<String>,
38
+ is_git_repo: bool
33
39
  ) -> Result<MerkleTree, anyhow::Error> {
34
40
  let path = PathBuf::from(absolute_path_to_root_directory.clone());
35
41
  if !path.exists() {
@@ -38,20 +44,21 @@ impl LocalConstruction for MerkleTree {
38
44
  }
39
45
 
40
46
  // 1. get all the gitignored files
41
- let git_ignored_files_and_dirs =
42
- match git_utils::list_ignored_files_and_directories(
43
- absolute_path_to_root_directory.as_str(),
44
- true,
45
- ) {
46
- Ok(git_ignored) => git_ignored,
47
- Err(_e) => HashSet::new(),
48
- };
47
+ // let git_ignored_files_and_dirs =
48
+ // match git_utils::list_ignored_files_and_directories(
49
+ // absolute_path_to_root_directory.as_str(),
50
+ // true,
51
+ // ) {
52
+ // Ok(git_ignored) => git_ignored,
53
+ // Err(_e) => HashSet::new(),
54
+ // };
49
55
 
50
56
  let root_node = MerkleNode::new(
51
57
  path,
52
58
  None,
53
59
  &git_ignored_files_and_dirs,
54
60
  absolute_path_to_root_directory.as_str(),
61
+ is_git_repo
55
62
  )
56
63
  .await;
57
64
  let mut mt = MerkleTree {
@@ -60,6 +67,7 @@ impl LocalConstruction for MerkleTree {
60
67
  root_path: absolute_path_to_root_directory,
61
68
  cursor: None,
62
69
  git_ignored_files_and_dirs: git_ignored_files_and_dirs,
70
+ is_git_repo
63
71
  };
64
72
 
65
73
  // we now iterate over all the nodes and add them to the hashmap
@@ -1,5 +1,3 @@
1
- use crate::git_utils;
2
-
3
1
  use super::file_utils;
4
2
  use sha2::Digest;
5
3
  use std::collections::{BTreeMap, HashSet};
@@ -9,6 +7,7 @@ use std::{fs, path::Path, sync::Arc};
9
7
  use tokio::sync::RwLock;
10
8
  use tonic::async_trait;
11
9
  use tracing::info;
10
+
12
11
  pub mod local_construction;
13
12
  pub mod test;
14
13
 
@@ -20,6 +19,7 @@ pub struct MerkleTree {
20
19
  files: BTreeMap<String, File>,
21
20
  cursor: Option<usize>,
22
21
  git_ignored_files_and_dirs: HashSet<String>,
22
+ is_git_repo: bool,
23
23
  }
24
24
 
25
25
  #[derive(Debug)]
@@ -63,6 +63,8 @@ pub trait LocalConstruction {
63
63
 
64
64
  async fn construct_merkle_tree(
65
65
  root_directory: String,
66
+ git_ignored_files_and_dirs: HashSet<String>,
67
+ is_git_repo: bool
66
68
  ) -> Result<MerkleTree, anyhow::Error>;
67
69
 
68
70
  async fn update_file(
@@ -97,6 +99,7 @@ impl MerkleTree {
97
99
  root_path: "".to_string(),
98
100
  cursor: None,
99
101
  git_ignored_files_and_dirs: HashSet::new(),
102
+ is_git_repo: false
100
103
  }
101
104
  }
102
105
 
@@ -287,6 +290,12 @@ impl MerkleTree {
287
290
  ) -> Result<Vec<String>, anyhow::Error> {
288
291
  let mut files = Vec::new();
289
292
 
293
+ // 1. should check that this absolute path is actually a directory.
294
+ let file_node = self.files.get(absolute_path);
295
+ if file_node.is_none() {
296
+ return Err(anyhow::anyhow!("Could not find directory the in tree!"));
297
+ }
298
+
290
299
  for (file_path, f) in &self.files {
291
300
  if !file_path.contains(absolute_path) {
292
301
  continue;
@@ -401,6 +410,7 @@ impl MerkleTree {
401
410
  Some(ancestor.clone()),
402
411
  &self.git_ignored_files_and_dirs,
403
412
  &absolute_root_path.as_str(),
413
+ self.is_git_repo
404
414
  )
405
415
  .await;
406
416
  ancestor.write().await.attach_child(new_node.clone()).await;
@@ -418,6 +428,7 @@ impl MerkleTree {
418
428
  Some(ancestor.clone()),
419
429
  &self.git_ignored_files_and_dirs,
420
430
  &absolute_root_path.as_str(),
431
+ self.is_git_repo
421
432
  )
422
433
  .await;
423
434
 
@@ -705,13 +716,14 @@ impl MerkleNode {
705
716
  parent: ParentPtr,
706
717
  ignored_files: &IgnoredFiles,
707
718
  absolute_root_path: &str,
719
+ is_git_repo: bool,
708
720
  ) -> MerkleNodePtr {
709
- // check if the root is a git directory.
710
- let is_git_repo =
711
- match git_utils::is_git_directory(absolute_root_path).await {
712
- Ok(is_git_repo) => is_git_repo,
713
- Err(e) => false,
714
- };
721
+ // // check if the root is a git directory.
722
+ // let is_git_repo =
723
+ // match git_utils::is_git_directory(absolute_root_path).await {
724
+ // Ok(is_git_repo) => is_git_repo,
725
+ // Err(_e) => false,
726
+ // };
715
727
  let bypass_git = !is_git_repo;
716
728
 
717
729
  MerkleNode::construct_node(
@@ -729,13 +741,8 @@ impl MerkleNode {
729
741
  parent: ParentPtr,
730
742
  ignored_files: &IgnoredFiles,
731
743
  absolute_root_path: &str,
744
+ is_git_repo: bool,
732
745
  ) -> MerkleNodePtr {
733
- // check if the root is a git directory.
734
- let is_git_repo =
735
- match git_utils::is_git_directory(absolute_root_path).await {
736
- Ok(is_git_repo) => is_git_repo,
737
- Err(_e) => false,
738
- };
739
746
  let bypass_git = !is_git_repo;
740
747
 
741
748
  info!(
@@ -883,18 +890,10 @@ impl MerkleNode {
883
890
  false => {}
884
891
  }
885
892
 
886
- // read the file_content to a buffer
887
- let file_content = match tokio::fs::read(absolute_file_path).await {
888
- Ok(content) => content,
889
- Err(e) => {
890
- return Err(format!("Could not read file! {}", e.to_string()));
891
- }
892
- };
893
-
894
893
  // check if the file passes runtime checks.
895
894
  match file_utils::is_good_file_runtime_check(
896
895
  absolute_file_path,
897
- &file_content,
896
+ // &file_content,
898
897
  )
899
898
  .await
900
899
  {
@@ -904,15 +903,14 @@ impl MerkleNode {
904
903
  }
905
904
  }
906
905
 
907
- let file_content = match std::str::from_utf8(&file_content) {
908
- Ok(content) => content,
909
- Err(e) => {
910
- return Err(format!(
911
- "UTF8 Failure. Could not convert file content to string! {}",
912
- e.to_string()
913
- ));
914
- }
915
- };
906
+ // read the file_content to a buffer
907
+ let file_content =
908
+ match file_utils::read_string_without_bom(absolute_file_path).await {
909
+ Ok(content) => content,
910
+ Err(e) => {
911
+ return Err(format!("Could not read file! {}", e.to_string()));
912
+ }
913
+ };
916
914
 
917
915
  let file_hash = compute_hash(&file_content);
918
916
  let node = MerkleNode {
@@ -43,8 +43,9 @@ mod tests {
43
43
  // let path = Path::new(&temp_dir_path);
44
44
 
45
45
  // Test construct_merkle_tree() function
46
+ let new_set = std::collections::HashSet::<String>::new();
46
47
  let tree =
47
- MerkleTree::construct_merkle_tree(temp_dir_path.clone()).await;
48
+ MerkleTree::construct_merkle_tree(temp_dir_path.clone(), new_set, false).await;
48
49
  let mut tree = match tree {
49
50
  Ok(tree) => {
50
51
  assert_eq!(tree.files.len(), 2);