@anysphere/file-service 0.0.0-e3fdf62d → 0.0.0-e9ef07ca

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,11 @@ version = "0.0.0"
6
6
  [lib]
7
7
  crate-type = ["cdylib"]
8
8
 
9
+ [features]
10
+ default = ["windows-subsystem"]
11
+ windows-subsystem = []
12
+ debugfile = []
13
+
9
14
  [dependencies]
10
15
  # Default enable napi4 feature, see https://nodejs.org/api/n-api.html#node-api-version-matrix
11
16
  napi = { version = "2.12.2", default-features = false, features = ["napi4", "async", "tokio_rt"] }
@@ -17,6 +22,12 @@ tempfile = "3.8.0"
17
22
  anyhow = "1.0.75"
18
23
  tonic = "0.9.2"
19
24
  prost = "0.11.9"
25
+ tracing = "0.1.37"
26
+ tracing-subscriber = "0.3.17"
27
+ tracing-appender = "0.2.2"
28
+ binaryornot = "1.0.0"
29
+ dunce = "1.0.1"
30
+ encoding_rs = "0.8.33"
20
31
 
21
32
  [build-dependencies]
22
33
  napi-build = "2.0.1"
@@ -24,5 +35,6 @@ tonic-build = "0.9.2"
24
35
  anyhow = "1.0.75"
25
36
  glob = "0.3.0"
26
37
 
38
+
27
39
  [profile.release]
28
40
  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
@@ -4,13 +4,17 @@
4
4
  /* auto-generated by NAPI-RS */
5
5
 
6
6
  export class MerkleClient {
7
- constructor(rootDirectory: string)
8
- init(): Promise<void>
7
+ constructor(absoluteRootDirectory: string)
8
+ init(gitIgnoredFiles: Array<string>, isGitRepo: boolean): Promise<void>
9
+ computeMerkleTree(gitIgnoredFiles: Array<string>, isGitRepo: boolean): Promise<void>
9
10
  updateFile(filePath: string): Promise<void>
10
11
  deleteFile(filePath: string): Promise<void>
11
- getSubtreeHash(path: string): Promise<string>
12
+ getSubtreeHash(relativePath: string): Promise<string>
12
13
  getNumEmbeddableFiles(): Promise<number>
13
14
  getAllFiles(): Promise<Array<string>>
15
+ getAllDirFilesToEmbed(absoluteFilePath: string): Promise<Array<string>>
14
16
  getNextFileToEmbed(): Promise<Array<string>>
17
+ getSpline(absoluteFilePath: string): Promise<Array<string>>
15
18
  getHashesForFiles(files: Array<string>): Promise<Array<string>>
19
+ updateRootDirectory(rootDirectory: string): void
16
20
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@anysphere/file-service",
3
- "version": "0.0.0-e3fdf62d",
3
+ "version": "0.0.0-e9ef07ca",
4
4
  "main": "index.js",
5
5
  "types": "index.d.ts",
6
6
  "napi": {
@@ -9,7 +9,8 @@
9
9
  "additional": [
10
10
  "aarch64-apple-darwin",
11
11
  "aarch64-pc-windows-msvc",
12
- "universal-apple-darwin"
12
+ "universal-apple-darwin",
13
+ "aarch64-unknown-linux-gnu"
13
14
  ]
14
15
  }
15
16
  },
@@ -35,11 +36,12 @@
35
36
  "version": "napi version"
36
37
  },
37
38
  "optionalDependencies": {
38
- "@anysphere/file-service-win32-x64-msvc": "0.0.0-e3fdf62d",
39
- "@anysphere/file-service-darwin-x64": "0.0.0-e3fdf62d",
40
- "@anysphere/file-service-linux-x64-gnu": "0.0.0-e3fdf62d",
41
- "@anysphere/file-service-darwin-arm64": "0.0.0-e3fdf62d",
42
- "@anysphere/file-service-win32-arm64-msvc": "0.0.0-e3fdf62d",
43
- "@anysphere/file-service-darwin-universal": "0.0.0-e3fdf62d"
39
+ "@anysphere/file-service-win32-x64-msvc": "0.0.0-e9ef07ca",
40
+ "@anysphere/file-service-darwin-x64": "0.0.0-e9ef07ca",
41
+ "@anysphere/file-service-linux-x64-gnu": "0.0.0-e9ef07ca",
42
+ "@anysphere/file-service-darwin-arm64": "0.0.0-e9ef07ca",
43
+ "@anysphere/file-service-win32-arm64-msvc": "0.0.0-e9ef07ca",
44
+ "@anysphere/file-service-darwin-universal": "0.0.0-e9ef07ca",
45
+ "@anysphere/file-service-linux-arm64-gnu": "0.0.0-e9ef07ca"
44
46
  }
45
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
 
@@ -12,9 +13,8 @@ pub fn is_in_bad_dir(file_path: &Path) -> Result<bool, Error> {
12
13
  let item_path = file_path
13
14
  .to_str()
14
15
  .ok_or(anyhow::anyhow!("Failed to convert path to string"))?;
15
- let is_bad_dir = (item_path.contains("node_modules")
16
- || item_path.contains(".git"))
17
- && !(item_path.ends_with(".git") || item_path.ends_with("node_modules"));
16
+ let is_bad_dir =
17
+ item_path.contains("node_modules") || item_path.contains(".git");
18
18
  Ok(is_bad_dir)
19
19
  }
20
20
 
@@ -38,14 +38,96 @@ pub fn is_good_file(file_path: &Path) -> Result<(), Error> {
38
38
 
39
39
  match file_name {
40
40
  "package-lock.json" | "pnpm-lock.yaml" | "yarn.lock" | "composer.lock"
41
- | "Gemfile.lock" => {
41
+ | "Gemfile.lock" | "bun.lockb" => {
42
42
  return Err(anyhow::anyhow!("File is just a lock file"));
43
43
  }
44
44
  _ => {}
45
45
  }
46
46
 
47
- match extension {
48
- "lock" | "bak" | "tmp" | "bin" | "exe" | "dll" | "so" => {
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 => {
49
131
  return Err(anyhow::anyhow!("File is just a lock file"));
50
132
  }
51
133
  _ => {}
@@ -63,7 +145,7 @@ pub fn is_good_file(file_path: &Path) -> Result<(), Error> {
63
145
  Some(extension) => match extension.to_str() {
64
146
  Some(ext_str) => {
65
147
  if bad_extensions.contains(&ext_str) {
66
- return Err(anyhow::anyhow!("File is not a valid UTF-8 string"));
148
+ return Err(anyhow::anyhow!("Binary file excluded from indexing."));
67
149
  }
68
150
  }
69
151
  None => {
@@ -89,10 +171,12 @@ pub fn is_good_file(file_path: &Path) -> Result<(), Error> {
89
171
  Ok(())
90
172
  }
91
173
 
174
+ // use binaryornot::is_binary;
175
+ // use anyhow::Context;
92
176
  // implement the buffer above:
93
177
  pub async fn is_good_file_runtime_check(
94
178
  file_path: &Path,
95
- buffer: &[u8],
179
+ // _buffer: &[u8],
96
180
  ) -> Result<(), Error> {
97
181
  match get_file_size(file_path).await {
98
182
  Ok(size) if size > 2 * 1024 * 1024 => {
@@ -102,16 +186,31 @@ pub async fn is_good_file_runtime_check(
102
186
  _ => {}
103
187
  }
104
188
 
105
- for &byte in buffer.iter().take(2048) {
106
- if byte.is_ascii() {
107
- continue;
108
- } else {
109
- return Err(anyhow::anyhow!("File is not a valid UTF-8 string"));
110
- }
111
- }
189
+ // if is_binary(file_path).context("Failed to check if file is binary")? {
190
+ // return Err(anyhow::anyhow!("File is binary"));
191
+ // }
192
+
112
193
  Ok(())
113
194
  }
114
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
+
115
214
  pub fn as_relative_path(
116
215
  base_path: &Path,
117
216
  file_path: &Path,
@@ -169,25 +268,40 @@ mod tests {
169
268
  temp_file.write_all(b"Hello, world!").await.unwrap();
170
269
  let buffer = fs::read(&temp_file_path).await.unwrap();
171
270
  assert_eq!(
172
- is_good_file_runtime_check(&temp_file_path, &buffer)
173
- .await
174
- .is_ok(),
271
+ is_good_file_runtime_check(&temp_file_path).await.is_ok(),
175
272
  true
176
273
  );
177
274
  temp_dir.close().unwrap();
178
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
179
294
  let temp_dir = tempfile::tempdir().unwrap();
180
295
  let temp_file_path = temp_dir.path().join("test_file");
181
296
  let mut temp_file = fs::File::create(&temp_file_path).await.unwrap();
182
- temp_file.write_all(&[0, 159, 146, 150]).await.unwrap(); // Invalid UTF-8 sequence
183
- let buffer = fs::read(&temp_file_path).await.unwrap();
184
- assert_eq!(
185
- is_good_file_runtime_check(&temp_file_path, &buffer)
186
- .await
187
- .is_err(),
188
- true
189
- );
190
- 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);
191
305
  }
192
306
 
193
307
  #[test]
package/src/git_utils.rs CHANGED
@@ -1,10 +1,11 @@
1
1
  use std::collections::HashSet;
2
- use std::path::PathBuf;
2
+ use std::path::MAIN_SEPARATOR_STR;
3
3
  use std::process::Command;
4
4
 
5
- pub fn list_ignored_files(
5
+ pub fn list_ignored_files_and_directories(
6
6
  workspace_root_path: &str,
7
- ) -> Result<HashSet<PathBuf>, Box<dyn std::error::Error>> {
7
+ should_return_absolute_paths: bool,
8
+ ) -> Result<HashSet<String>, Box<dyn std::error::Error>> {
8
9
  let mut gitignored_files = HashSet::new();
9
10
 
10
11
  let commands = vec![
@@ -14,13 +15,70 @@ pub fn list_ignored_files(
14
15
  "--others",
15
16
  "--ignored",
16
17
  "--exclude-standard",
18
+ "--directory",
19
+ "--no-empty-directory"
17
20
  ],
21
+ // FIXME(sualeh): this is super sketchy and might totally break in like a bazillion ways. i dont like it.
22
+ vec![
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)'",
24
+ ],
25
+ ];
26
+
27
+ for command in commands {
28
+ let output = Command::new(&command[0])
29
+ .args(&command[1..])
30
+ .current_dir(workspace_root_path)
31
+ .output()?;
32
+
33
+ if output.status.success() {
34
+ let files = String::from_utf8(output.stdout)?
35
+ .lines()
36
+ .filter(|line| !line.is_empty())
37
+ .map(|line| {
38
+ let line = line.replace("/", MAIN_SEPARATOR_STR);
39
+
40
+ if should_return_absolute_paths {
41
+ let mut path = std::path::PathBuf::from(workspace_root_path);
42
+
43
+ path.push(line.clone());
44
+
45
+ match path.canonicalize() {
46
+ Ok(canonical_path) => {
47
+ canonical_path.to_string_lossy().into_owned()
48
+ }
49
+ Err(_) => String::from(line),
50
+ }
51
+ } else {
52
+ String::from(line)
53
+ }
54
+ })
55
+ .collect::<HashSet<_>>();
56
+
57
+ gitignored_files.extend(files);
58
+ }
59
+ }
60
+
61
+ Ok(gitignored_files)
62
+ }
63
+
64
+ pub fn list_ignored_files_with_absolute_paths(
65
+ workspace_root_path: &str,
66
+ ) -> Result<HashSet<String>, Box<dyn std::error::Error>> {
67
+ let mut gitignored_files = HashSet::new();
68
+
69
+ let commands = vec![
18
70
  vec![
19
71
  "git",
20
- "submodule",
21
- "foreach",
22
- "--quiet",
23
- "git ls-files --others --ignored --exclude-standard | sed 's|^|$path/|'",
72
+ "ls-files",
73
+ "--others",
74
+ "--ignored",
75
+ "--exclude-standard",
76
+ ],
77
+ // FIXME(sualeh): this is super sketchy and might totally break in like a bazillion ways. i dont like it.
78
+ vec![
79
+ "sh",
80
+ "-c",
81
+ "git submodule foreach --quiet 'git ls-files --others --ignored --exclude-standard | sed \"s|^|$path/|\"'",
24
82
  ],
25
83
  ];
26
84
 
@@ -34,7 +92,7 @@ pub fn list_ignored_files(
34
92
  let files = String::from_utf8(output.stdout)?
35
93
  .lines()
36
94
  .filter(|line| !line.is_empty())
37
- .map(|line| PathBuf::from(line))
95
+ .map(|line| String::from(line))
38
96
  .collect::<HashSet<_>>();
39
97
 
40
98
  gitignored_files.extend(files);
@@ -57,6 +115,18 @@ pub async fn is_git_ignored(
57
115
  Ok(output.status.success())
58
116
  }
59
117
 
118
+ pub async fn is_git_directory(
119
+ workspace_root_path: &str,
120
+ ) -> Result<bool, anyhow::Error> {
121
+ let output = tokio::process::Command::new("git")
122
+ .args(&["rev-parse", "--is-inside-work-tree"])
123
+ .current_dir(workspace_root_path)
124
+ .output()
125
+ .await?;
126
+
127
+ Ok(output.status.success())
128
+ }
129
+
60
130
  #[cfg(test)]
61
131
  mod tests {
62
132
  use super::*;
@@ -66,7 +136,9 @@ mod tests {
66
136
  #[test]
67
137
  fn test_no_ignored_files() {
68
138
  let dir = tempfile::tempdir().unwrap();
69
- let gitignored_files = list_ignored_files(dir.path().to_str().unwrap()).unwrap();
139
+ let gitignored_files =
140
+ list_ignored_files_and_directories(dir.path().to_str().unwrap(), false)
141
+ .unwrap();
70
142
  Command::new("git")
71
143
  .args(&["init"])
72
144
  .current_dir(dir.path())
@@ -92,13 +164,15 @@ mod tests {
92
164
  .current_dir(dir.path())
93
165
  .output()
94
166
  .unwrap();
95
- let gitignored_files = list_ignored_files(dir.path().to_str().unwrap()).unwrap();
167
+ let gitignored_files =
168
+ list_ignored_files_and_directories(dir.path().to_str().unwrap(), false)
169
+ .unwrap();
96
170
  println!(
97
171
  "ignored files for test_one_ignored_file: {:?}",
98
172
  gitignored_files
99
173
  );
100
174
  // assert_eq!(gitignored_files.len(), 1);
101
- assert!(gitignored_files.contains(&PathBuf::from("ignored.txt")));
175
+ assert!(gitignored_files.contains(&String::from("ignored.txt")));
102
176
  }
103
177
 
104
178
  #[test]
@@ -121,19 +195,86 @@ mod tests {
121
195
  .current_dir(dir.path())
122
196
  .output()
123
197
  .unwrap();
124
- let gitignored_files = list_ignored_files(dir.path().to_str().unwrap()).unwrap();
198
+ let gitignored_files =
199
+ list_ignored_files_and_directories(dir.path().to_str().unwrap(), false)
200
+ .unwrap();
125
201
  println!(
126
202
  "ignored files for test_multiple_ignored_files: {:?}",
127
203
  gitignored_files
128
204
  );
129
205
  // assert_eq!(gitignored_files.len(), 2);
130
- assert!(gitignored_files.contains(&PathBuf::from("ignored1.txt")));
131
- assert!(gitignored_files.contains(&PathBuf::from("ignored2.txt")));
206
+ assert!(gitignored_files.contains(&String::from("ignored1.txt")));
207
+ assert!(gitignored_files.contains(&String::from("ignored2.txt")));
208
+ }
209
+
210
+ #[test]
211
+ fn test_git_submodule_ignored_files() {
212
+ let dir = tempfile::tempdir().unwrap();
213
+ let submodule_path = dir.path().join("submodule");
214
+ std::fs::create_dir(&submodule_path).unwrap();
215
+
216
+ let o = Command::new("git")
217
+ .args(&["init"])
218
+ .current_dir(&submodule_path)
219
+ .output()
220
+ .unwrap();
221
+ println!("git init output: {:?}", o);
222
+
223
+ let file_path = submodule_path.join("ignored.txt");
224
+ let mut file = File::create(&file_path).unwrap();
225
+ writeln!(file, "This is an ignored file.").unwrap();
226
+
227
+ let file2 = submodule_path.join("ignored2.txt");
228
+ let mut file = File::create(&file2).unwrap();
229
+ writeln!(file, "This is another ignored file.").unwrap();
230
+
231
+ let gitignore_path = submodule_path.join(".gitignore");
232
+ let mut gitignore = File::create(&gitignore_path).unwrap();
233
+ writeln!(gitignore, "*.txt").unwrap();
234
+
235
+ let o = Command::new("git")
236
+ .args(&["init"])
237
+ .current_dir(dir.path())
238
+ .output()
239
+ .unwrap();
240
+ println!("git init output: {:?}", o);
241
+
242
+ // make a commit in the submodule
243
+ let o = Command::new("git")
244
+ .args(&["add", "."])
245
+ .current_dir(&submodule_path)
246
+ .output()
247
+ .unwrap();
248
+ println!("git add output: {:?}", o);
249
+ let o = Command::new("git")
250
+ .args(&["commit", "-m", "initial commit"])
251
+ .current_dir(&submodule_path)
252
+ .output()
253
+ .unwrap();
254
+ println!("git commit output: {:?}", o);
255
+
256
+ let o = Command::new("git")
257
+ .args(&["submodule", "add", "./submodule"])
258
+ .current_dir(dir.path())
259
+ .output()
260
+ .unwrap();
261
+ println!("git submodule add output: {:?}", o);
262
+
263
+ let gitignored_files =
264
+ list_ignored_files_and_directories(dir.path().to_str().unwrap(), false)
265
+ .unwrap();
266
+ println!(
267
+ "ignored files for test_git_submodule_ignored_files: {:?}",
268
+ gitignored_files
269
+ );
270
+ assert!(gitignored_files.contains(&String::from("submodule/ignored.txt")));
271
+ assert!(gitignored_files.contains(&String::from("submodule/ignored2.txt")));
132
272
  }
133
273
 
134
274
  #[test]
135
275
  fn test_multiple_ignored_files_in_current_dir() {
136
- let gitignored_files = list_ignored_files(".").unwrap();
276
+ let gitignored_files =
277
+ list_ignored_files_and_directories(".", false).unwrap();
137
278
  assert!(gitignored_files.len() > 1);
138
279
 
139
280
  // print a sample of the ignored files
@@ -147,7 +288,6 @@ mod tests {
147
288
  }
148
289
  }
149
290
 
150
-
151
291
  #[tokio::test]
152
292
  async fn test_file_not_ignored() {
153
293
  let dir = tempfile::tempdir().unwrap();
@@ -160,7 +300,10 @@ mod tests {
160
300
  .current_dir(dir.path())
161
301
  .output()
162
302
  .unwrap();
163
- let is_ignored = is_git_ignored(dir.path().to_str().unwrap(), "not_ignored.txt").await.unwrap();
303
+ let is_ignored =
304
+ is_git_ignored(dir.path().to_str().unwrap(), "not_ignored.txt")
305
+ .await
306
+ .unwrap();
164
307
  assert_eq!(is_ignored, false);
165
308
  }
166
309
 
@@ -180,7 +323,10 @@ mod tests {
180
323
  .current_dir(dir.path())
181
324
  .output()
182
325
  .unwrap();
183
- let is_ignored = is_git_ignored(dir.path().to_str().unwrap(), "ignored.txt").await.unwrap();
326
+ let is_ignored =
327
+ is_git_ignored(dir.path().to_str().unwrap(), "ignored.txt")
328
+ .await
329
+ .unwrap();
184
330
  assert_eq!(is_ignored, true);
185
331
  }
186
332
 
@@ -200,8 +346,10 @@ mod tests {
200
346
  .current_dir(dir.path())
201
347
  .output()
202
348
  .unwrap();
203
- let is_ignored = is_git_ignored(dir.path().to_str().unwrap(), "ignored.txt").await.unwrap();
349
+ let is_ignored =
350
+ is_git_ignored(dir.path().to_str().unwrap(), "ignored.txt")
351
+ .await
352
+ .unwrap();
204
353
  assert_eq!(is_ignored, true);
205
354
  }
206
-
207
355
  }