Skip to main content

fluidattacks_core_git/
fs.rs

1use 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}