Skip to main content

plot/lib/logic/path/
path_scan.rs

1use walkdir::WalkDir;
2
3use crate::lib::logic::{AnchoredPathsDatum, PathNode};
4
5/// Statystyki skanowania systemu plików
6#[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/// Skaner systemu plików (warstwa IO)
15#[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}