fluidattacks_core_git/
fs.rs1use anyhow::Result;
2use ignore::gitignore::GitignoreBuilder;
3use std::fs;
4use std::path::Path;
5use walkdir::WalkDir;
6
7pub fn remove_symlinks(dir: &Path) -> Result<()> {
8 for entry in WalkDir::new(dir) {
9 let entry = entry?;
10 let metadata = entry.path().symlink_metadata()?;
11 if metadata.file_type().is_symlink() {
12 fs::remove_file(entry.path())?;
13 }
14 }
15 Ok(())
16}
17
18pub fn delete_gitignored_files(repo_path: &Path, patterns: &[String]) -> Result<()> {
19 let mut builder = GitignoreBuilder::new(repo_path);
20 for pattern in patterns {
21 builder.add_line(None, pattern)?;
22 }
23 let gitignore = builder.build()?;
24
25 for entry in WalkDir::new(repo_path) {
26 let entry = entry?;
27 let path = entry.path();
28
29 let Ok(rel) = path.strip_prefix(repo_path) else {
30 continue;
31 };
32
33 let rel_str = rel.to_string_lossy();
34
35 if rel_str == ".git" || rel_str.starts_with(".git/") || rel_str.starts_with(".git\\") {
36 continue;
37 }
38
39 if rel_str.is_empty() {
40 continue;
41 }
42
43 if !entry.file_type().is_dir() && gitignore.matched(rel, false).is_ignore() {
44 let _ = fs::remove_file(path);
45 }
46 }
47
48 remove_empty_dirs(repo_path)?;
49 Ok(())
50}
51
52pub fn copy_dir_all(src: &Path, dst: &Path) -> Result<()> {
53 fs::create_dir_all(dst)?;
54 for entry in fs::read_dir(src)? {
55 let entry = entry?;
56 let ty = entry.file_type()?;
57 let dst_path = dst.join(entry.file_name());
58 if ty.is_dir() {
59 copy_dir_all(&entry.path(), &dst_path)?;
60 } else {
61 fs::copy(entry.path(), &dst_path)?;
62 }
63 }
64 Ok(())
65}
66
67fn remove_empty_dirs(root: &Path) -> Result<()> {
68 let mut dirs: Vec<_> = Vec::new();
69
70 for entry in WalkDir::new(root) {
71 let entry = entry?;
72 let path = entry.path();
73
74 let Ok(rel) = path.strip_prefix(root) else {
75 continue;
76 };
77
78 let rel_str = rel.to_string_lossy();
79
80 if rel_str == ".git" || rel_str.starts_with(".git/") || rel_str.starts_with(".git\\") {
81 continue;
82 }
83
84 if entry.file_type().is_dir() && path != root {
85 dirs.push(path.to_path_buf());
86 }
87 }
88
89 dirs.sort();
90 dirs.reverse();
91
92 for dir in dirs {
93 if let Ok(entries) = fs::read_dir(&dir) {
94 if entries.count() == 0 {
95 let _ = fs::remove_dir(&dir);
96 }
97 }
98 }
99
100 Ok(())
101}