plot/lib/logic/path/
path_scan.rs1use walkdir::WalkDir;
2
3use crate::lib::logic::{AnchoredPathsDatum, PathNode};
4
5#[derive(Debug, Clone)]
7pub struct ScanPathStat {
8 pub count_files: usize,
9 pub count_folder: usize,
10 pub count_empty: usize,
11 pub relation: AnchoredPathsDatum,
12}
13
14#[derive(Debug, Clone)]
16pub struct ScannedToApply {
17 pub files: Vec<PathNode>,
18 pub dirs: Vec<PathNode>,
19 pub stat: ScanPathStat,
20}
21
22impl ScannedToApply {
23 pub fn scan(relation: &AnchoredPathsDatum) -> Self {
24 let mut files = Vec::new();
25 let mut dirs = Vec::new();
26
27 let mut count_files = 0;
28 let mut count_folder = 0;
29 let mut count_empty = 0;
30
31 let root = &relation.select_dir.buf;
32
33 for e in WalkDir::new(root).into_iter().filter_map(|e| e.ok()) {
34 if e.depth() == 0 {
35 continue;
36 }
37
38 if e.path_is_symlink() {
39 continue;
40 }
41
42 let Ok(rel_path) = e.path().strip_prefix(root) else {
43 continue;
44 };
45
46 let mut path = rel_path.to_string_lossy().replace('\\', "/");
47
48 if e.file_type().is_dir() {
49 path.push('/');
50 count_folder += 1;
51
52 let is_empty = e.metadata().map(|m| m.is_dir()).unwrap_or(false)
53 && e.path().read_dir().map(|mut r| r.next().is_none()).unwrap_or(false);
54
55 if is_empty {
56 count_empty += 1;
57 }
58
59 dirs.push(PathNode::new(format!("./{}", path).into()));
60 } else {
61 count_files += 1;
62
63 files.push(PathNode::new(format!("./{}", path).into()));
64 }
65 }
66
67 files.sort_unstable_by(|a, b| a.str.cmp(&b.str));
68 dirs.sort_unstable_by(|a, b| a.str.cmp(&b.str));
69
70 let stat = ScanPathStat { count_files, count_folder, count_empty, relation: relation.clone() };
71
72 Self { files, dirs, stat }
73 }
74
75 pub fn files(&self) -> &[PathNode] { &self.files }
76
77 pub fn dirs(&self) -> &[PathNode] { &self.dirs }
78
79 fn to_strs(v: &[PathNode]) -> impl Iterator<Item = &str> + '_ { v.iter().map(|p| p.str.as_str()) }
80
81 pub fn file_strs(&self) -> impl Iterator<Item = &str> + '_ { Self::to_strs(&self.files) }
82
83 pub fn dir_strs(&self) -> impl Iterator<Item = &str> + '_ { Self::to_strs(&self.dirs) }
84}