@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 +12 -0
- package/build.rs +2 -0
- package/index.d.ts +7 -3
- package/package.json +10 -8
- package/src/file_utils.rs +141 -27
- package/src/git_utils.rs +168 -20
- package/src/lib.rs +190 -16
- package/src/merkle_tree/local_construction.rs +48 -9
- package/src/merkle_tree/mod.rs +332 -115
- package/src/merkle_tree/test.rs +2 -1
- package/src/test.rs +5 -0
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
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(
|
|
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(
|
|
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-
|
|
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-
|
|
39
|
-
"@anysphere/file-service-darwin-x64": "0.0.0-
|
|
40
|
-
"@anysphere/file-service-linux-x64-gnu": "0.0.0-
|
|
41
|
-
"@anysphere/file-service-darwin-arm64": "0.0.0-
|
|
42
|
-
"@anysphere/file-service-win32-arm64-msvc": "0.0.0-
|
|
43
|
-
"@anysphere/file-service-darwin-universal": "0.0.0-
|
|
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 =
|
|
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
|
-
|
|
48
|
-
"lock"
|
|
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!("
|
|
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
|
-
|
|
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
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
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,
|
|
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(&
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
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::
|
|
2
|
+
use std::path::MAIN_SEPARATOR_STR;
|
|
3
3
|
use std::process::Command;
|
|
4
4
|
|
|
5
|
-
pub fn
|
|
5
|
+
pub fn list_ignored_files_and_directories(
|
|
6
6
|
workspace_root_path: &str,
|
|
7
|
-
|
|
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
|
-
"
|
|
21
|
-
"
|
|
22
|
-
"--
|
|
23
|
-
"
|
|
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|
|
|
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 =
|
|
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 =
|
|
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(&
|
|
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 =
|
|
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(&
|
|
131
|
-
assert!(gitignored_files.contains(&
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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
|
}
|