Walk a repository directory and collect metadata for all non-binary source files. Uses the `ignore` crate to automatically respect .gitignore rules and skip .git directories, with `should_skip_dir()` as an additional filter for common non-gitignored directories (node_modules, target, etc.).
(repo_path: &Path)
| 198 | /// and skip .git directories, with `should_skip_dir()` as an additional filter |
| 199 | /// for common non-gitignored directories (node_modules, target, etc.). |
| 200 | pub fn walk_source_files(repo_path: &Path) -> Vec<FileInfo> { |
| 201 | let mut files = Vec::new(); |
| 202 | |
| 203 | let walker = ignore::WalkBuilder::new(repo_path) |
| 204 | .hidden(false) |
| 205 | .follow_links(false) |
| 206 | .filter_entry(|entry| { |
| 207 | if entry.file_type().map(|ft| ft.is_dir()).unwrap_or(false) { |
| 208 | if let Some(name) = entry.file_name().to_str() { |
| 209 | return !should_skip_dir(name); |
| 210 | } |
| 211 | } |
| 212 | true |
| 213 | }) |
| 214 | .build(); |
| 215 | |
| 216 | for entry in walker { |
| 217 | let Ok(entry) = entry else { continue }; |
| 218 | if !entry.file_type().map(|ft| ft.is_file()).unwrap_or(false) { |
| 219 | continue; |
| 220 | } |
| 221 | |
| 222 | let path = entry.path(); |
| 223 | if is_binary(path) { |
| 224 | continue; |
| 225 | } |
| 226 | |
| 227 | let name = entry.file_name().to_str().unwrap_or("").to_string(); |
| 228 | |
| 229 | let extension = path |
| 230 | .extension() |
| 231 | .and_then(|e| e.to_str()) |
| 232 | .unwrap_or("") |
| 233 | .to_string(); |
| 234 | |
| 235 | // Compute a relative path from repo_path |
| 236 | let rel_path = path |
| 237 | .strip_prefix(repo_path) |
| 238 | .unwrap_or(path) |
| 239 | .to_string_lossy() |
| 240 | .to_string(); |
| 241 | |
| 242 | let directory = path |
| 243 | .parent() |
| 244 | .map(|p| { |
| 245 | p.strip_prefix(repo_path) |
| 246 | .unwrap_or(p) |
| 247 | .to_string_lossy() |
| 248 | .to_string() |
| 249 | }) |
| 250 | .unwrap_or_default(); |
| 251 | |
| 252 | let metadata = entry.metadata().ok(); |
| 253 | let size = metadata.as_ref().map(|m| m.len()).unwrap_or(0); |
| 254 | let modified_at = metadata |
| 255 | .and_then(|m| m.modified().ok()) |
| 256 | .map(|t| { |
| 257 | let dt: chrono::DateTime<chrono::Utc> = t.into(); |
no test coverage detected