1use std::{fs, path::Path};
2
3use anyhow::{Context, Result};
4use chrono::DateTime;
5
6use crate::lib::{job, logic};
7
8pub trait AsScannedNode {
14 fn as_scanned_node(&self) -> logic::ScannedNode;
15}
16
17impl AsScannedNode for logic::ScannedFileNode {
18 fn as_scanned_node(&self) -> logic::ScannedNode {
19 logic::ScannedNode {
20 name: self.name.clone(),
21 path: self.path.clone(),
22 node: logic::NodeIs::File,
23 tier: self.tier,
24 id_self: self.id_self, id_path: self.id_path.clone(), dir_has_subdirs: None,
27 dir_has_files_binary: None,
28 dir_has_files_text: None,
29 dir_has_symlinks: None,
30 file_is_binary: Some(self.is_binary),
31 file_is_empty: Some(self.is_empty),
32 }
33 }
34}
35
36impl AsScannedNode for logic::ScannedDirNode {
37 fn as_scanned_node(&self) -> logic::ScannedNode {
38 logic::ScannedNode {
39 name: self.name.clone(),
40 path: self.path.clone(),
41 node: logic::NodeIs::Dir,
42 tier: self.tier,
43 id_self: self.id_self, id_path: self.id_path.clone(), dir_has_subdirs: Some(self.has_subdirs),
46 dir_has_files_binary: Some(self.has_files_binary),
47 dir_has_files_text: Some(self.has_files_text),
48 dir_has_symlinks: Some(self.has_symlinks),
49 file_is_binary: None,
50 file_is_empty: None,
51 }
52 }
53}
54
55fn piece_gather<L>(a: &logic::AnchoredPathsDatum, p: &logic::Partition<L>) -> Vec<job::ValidResultMainRow>
61where
62 L: logic::MatchLabel,
63 L::Node: AsScannedNode, {
65 p.nodes
66 .iter()
67 .filter_map(|n| {
68 let unified_node = n.as_scanned_node();
69 data_inspect(a, unified_node).ok() })
71 .collect()
72}
73
74fn data_inspect(a: &logic::AnchoredPathsDatum, scanned_node: logic::ScannedNode) -> Result<job::ValidResultMainRow> {
76 let clean_rel = scanned_node.path.str.strip_prefix("./").unwrap_or(&scanned_node.path.str);
79 let absolute_path = a.workspace_dir.buf.join(clean_rel);
80
81 let metadata = fs::metadata(&absolute_path).context("Nie można odczytać metadanych")?;
83
84 let dt_modified = DateTime::from(metadata.modified()?);
86
87 let name_with_ext = absolute_path.file_name().unwrap_or_default().to_string_lossy().to_string();
88
89 let size_real = if metadata.is_dir() { get_dir_size(&absolute_path) } else { metadata.len() };
90
91 Ok(job::ValidResultMainRow { dt_modified, name_with_ext, size_real, node: scanned_node })
92}
93
94fn get_dir_size(path: &Path) -> u64 {
96 walkdir::WalkDir::new(path)
97 .into_iter()
98 .filter_map(|e| e.ok())
99 .filter(|e| e.file_type().is_file())
100 .filter_map(|e| e.metadata().ok())
101 .map(|m| m.len())
102 .sum()
103}
104
105pub fn data_gather(
109 a: &logic::AnchoredPathsDatum,
110 b: &logic::PartitionScanned,
111 c: job::ValidTablePartConfig,
112) -> job::ValidResultMainTab {
113 let mut final_rows = Vec::new();
114 let mut t_max = 0;
115 let mut n_max = 0;
116 let mut p_max = 0;
117
118 if c.md {
120 final_rows.extend(piece_gather(a, &b.m_d));
121 t_max = t_max.max(b.m_d.tier_max);
122 n_max = n_max.max(b.m_d.name_len_max);
123 p_max = p_max.max(b.m_d.path_len_max);
124 }
125 if c.mf {
126 final_rows.extend(piece_gather(a, &b.m_f));
127 t_max = t_max.max(b.m_f.tier_max);
128 n_max = n_max.max(b.m_f.name_len_max);
129 p_max = p_max.max(b.m_f.path_len_max);
130 }
131 if c.xd {
132 final_rows.extend(piece_gather(a, &b.x_d));
133 t_max = t_max.max(b.x_d.tier_max);
134 n_max = n_max.max(b.x_d.name_len_max);
135 p_max = p_max.max(b.x_d.path_len_max);
136 }
137 if c.xf {
138 final_rows.extend(piece_gather(a, &b.x_f));
139 t_max = t_max.max(b.x_f.tier_max);
140 n_max = n_max.max(b.x_f.name_len_max);
141 p_max = p_max.max(b.x_f.path_len_max);
142 }
143
144 final_rows.sort_unstable_by(|row_a, row_b| row_a.node.path.str.cmp(&row_b.node.path.str));
146
147 job::ValidResultMainTab { rows: final_rows, tier_max: t_max, name_len_max: n_max, path_len_max: p_max }
148}
149pub fn engine_step1_scanner(
152 c: job::ValidTablePartConfig,
153 workspace: &job::ValidWorkspaceConfig, patterns: &job::ValidPatternConfig, ) -> job::ValidResultMainTab {
156 let anchored_paths_datum = workspace.get();
158 let patterns_queries = patterns.get();
159
160 let partition_scanned = logic::PartitionScanned::scan(&anchored_paths_datum, &patterns_queries);
162
163 data_gather(&anchored_paths_datum, &partition_scanned, c)
165}