1use std::{fs, path::Path};
2
3use anyhow::{Context, Result};
4use chrono::{DateTime, Local};
5
6use crate::lib::{job, logic};
7
8#[derive(Debug, Clone)]
15pub struct RawRow {
16 pub dt_modified: DateTime<Local>,
17 pub name_with_ext: String,
18 pub size_real: u64,
19 pub node: logic::ScannedNode,
20}
21pub struct ScannedTable {
22 pub rows: Vec<RawRow>,
23 pub tier_max: usize,
24 pub name_len_max: usize,
25}
26
27pub trait AsScannedNode {
33 fn as_scanned_node(&self) -> logic::ScannedNode;
34}
35
36impl AsScannedNode for logic::ScannedFileNode {
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::File,
42 tier: self.tier,
43 dir_has_subdirs: None,
44 dir_has_files_binary: None,
45 dir_has_files_text: None,
46 dir_has_symlinks: None,
47 file_is_binary: Some(self.is_binary),
48 file_is_empty: Some(self.is_empty),
49 }
50 }
51}
52
53impl AsScannedNode for logic::ScannedDirNode {
54 fn as_scanned_node(&self) -> logic::ScannedNode {
55 logic::ScannedNode {
56 name: self.name.clone(),
57 path: self.path.clone(),
58 node: logic::NodeIs::Dir,
59 tier: self.tier,
60 dir_has_subdirs: Some(self.has_subdirs),
61 dir_has_files_binary: Some(self.has_files_binary),
62 dir_has_files_text: Some(self.has_files_text),
63 dir_has_symlinks: Some(self.has_symlinks),
64 file_is_binary: None,
65 file_is_empty: None,
66 }
67 }
68}
69
70fn piece_gather<L>(a: &logic::AnchoredPathsDatum, p: &logic::Partition<L>) -> Vec<RawRow>
76where
77 L: logic::MatchLabel,
78 L::Node: AsScannedNode, {
80 p.nodes
81 .iter()
82 .filter_map(|n| {
83 let unified_node = n.as_scanned_node();
84 data_inspect(a, unified_node).ok() })
86 .collect()
87}
88
89fn data_inspect(a: &logic::AnchoredPathsDatum, scanned_node: logic::ScannedNode) -> Result<RawRow> {
91 let clean_rel = scanned_node.path.str.strip_prefix("./").unwrap_or(&scanned_node.path.str);
94 let absolute_path = a.workspace_dir.buf.join(clean_rel);
95
96 let metadata = fs::metadata(&absolute_path).context("Nie można odczytać metadanych")?;
98
99 let dt_modified = DateTime::from(metadata.modified()?);
101
102 let name_with_ext = absolute_path.file_name().unwrap_or_default().to_string_lossy().to_string();
103
104 let size_real = if metadata.is_dir() { get_dir_size(&absolute_path) } else { metadata.len() };
105
106 Ok(RawRow { dt_modified, name_with_ext, size_real, node: scanned_node })
107}
108
109fn get_dir_size(path: &Path) -> u64 {
111 walkdir::WalkDir::new(path)
112 .into_iter()
113 .filter_map(|e| e.ok())
114 .filter(|e| e.file_type().is_file())
115 .filter_map(|e| e.metadata().ok())
116 .map(|m| m.len())
117 .sum()
118}
119
120pub fn data_gather(
124 a: &logic::AnchoredPathsDatum,
125 b: &logic::PartitionScanned,
126 c: job::ValidTablePartConfig,
127) -> ScannedTable {
128 let mut final_rows = Vec::new();
129 let mut t_max = 0;
130 let mut n_max = 0;
131
132 if c.md {
134 final_rows.extend(piece_gather(a, &b.m_d));
135 t_max = t_max.max(b.m_d.tier_max);
136 n_max = n_max.max(b.m_d.name_len_max);
137 }
138 if c.mf {
139 final_rows.extend(piece_gather(a, &b.m_f));
140 t_max = t_max.max(b.m_f.tier_max);
141 n_max = n_max.max(b.m_f.name_len_max);
142 }
143 if c.xd {
144 final_rows.extend(piece_gather(a, &b.x_d));
145 t_max = t_max.max(b.x_d.tier_max);
146 n_max = n_max.max(b.x_d.name_len_max);
147 }
148 if c.xf {
149 final_rows.extend(piece_gather(a, &b.x_f));
150 t_max = t_max.max(b.x_f.tier_max);
151 n_max = n_max.max(b.x_f.name_len_max);
152 }
153
154 final_rows.sort_unstable_by(|row_a, row_b| row_a.node.path.str.cmp(&row_b.node.path.str));
156
157 ScannedTable { rows: final_rows, tier_max: t_max, name_len_max: n_max }
158}
159pub fn engine_step1_scanner(
162 c: job::ValidTablePartConfig,
163 workspace: &job::ValidWorkspaceConfig, patterns: &job::ValidPatternConfig, ) -> ScannedTable {
166 let anchored_paths_datum = workspace.get();
168 let patterns_queries = patterns.get();
169
170 let partition_scanned = logic::PartitionScanned::scan(&anchored_paths_datum, &patterns_queries);
172
173 data_gather(&anchored_paths_datum, &partition_scanned, c)
175}
176
177