Files
wtismycode/archdoc-core/src/scanner.rs
Arkasha 9f823d2a2a refactor: decompose CLI into commands, fix clippy, improve error handling
- Decompose main.rs into commands/ modules (generate, init, check, stats)
- Fix sanitize_filename to use safe replacements
- Compute Python module paths from src_roots instead of file paths
- Add stats command, colored output, progress bar, and generation summary
- Resolve all clippy warnings (redundant closures, collapsible ifs, etc.)
- Replace last unwrap() with proper error handling
- Add target/ to .gitignore, remove target/ artifacts from git tracking
2026-02-15 03:23:01 +03:00

81 lines
2.4 KiB
Rust

//! File scanner for ArchDoc
//!
//! This module handles scanning the file system for Python files according to
//! the configuration settings.
use crate::config::Config;
use crate::errors::ArchDocError;
use std::path::{Path, PathBuf};
use walkdir::WalkDir;
pub struct FileScanner {
config: Config,
}
impl FileScanner {
pub fn new(config: Config) -> Self {
Self { config }
}
pub fn scan_python_files(&self, root: &Path) -> Result<Vec<PathBuf>, ArchDocError> {
// Check if root directory exists
if !root.exists() {
return Err(ArchDocError::Io(std::io::Error::new(
std::io::ErrorKind::NotFound,
format!("Root directory does not exist: {}", root.display())
)));
}
if !root.is_dir() {
return Err(ArchDocError::Io(std::io::Error::new(
std::io::ErrorKind::InvalidInput,
format!("Root path is not a directory: {}", root.display())
)));
}
let mut python_files = Vec::new();
// Walk directory tree respecting include/exclude patterns
for entry in WalkDir::new(root)
.follow_links(self.config.scan.follow_symlinks)
.into_iter() {
let entry = entry.map_err(|e| {
ArchDocError::Io(std::io::Error::other(
format!("Failed to read directory entry: {}", e)
))
})?;
let path = entry.path();
// Skip excluded paths
if self.is_excluded(path) {
continue;
}
// Include Python files
if path.extension().and_then(|s| s.to_str()) == Some("py") {
python_files.push(path.to_path_buf());
}
}
Ok(python_files)
}
fn is_excluded(&self, path: &Path) -> bool {
// Convert path to string for pattern matching
let path_str = match path.to_str() {
Some(s) => s,
None => return false, // If we can't convert to string, don't exclude
};
// Check if path matches any exclude patterns
for pattern in &self.config.scan.exclude {
if path_str.contains(pattern) {
return true;
}
}
false
}
}