-
Notifications
You must be signed in to change notification settings - Fork 9
feat: add --ignore-ext and --only-ext flags for extension filtering #13
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
95e27b2
6ef0f8e
82eefef
150f89e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -39,6 +39,14 @@ pub struct Config { | |
| #[serde(default)] | ||
| pub custom_paths: Vec<CustomCleanPath>, | ||
|
|
||
| /// File extensions to ignore during scanning | ||
| #[serde(default)] | ||
| pub ignored_extensions: Vec<String>, | ||
|
|
||
| /// When set, only include files with these extensions | ||
| #[serde(default)] | ||
| pub only_extensions: Vec<String>, | ||
|
|
||
| /// Base path for scanning (default: home directory) | ||
| #[serde(skip)] | ||
| pub base_path: Option<PathBuf>, | ||
|
|
@@ -139,6 +147,8 @@ impl Default for Config { | |
| excluded_paths: Vec::new(), | ||
| cache_paths: Vec::new(), | ||
| custom_paths: Vec::new(), | ||
| ignored_extensions: Vec::new(), | ||
| only_extensions: Vec::new(), | ||
| base_path: None, | ||
| } | ||
| } | ||
|
|
@@ -164,9 +174,18 @@ impl Config { | |
| let contents = fs::read_to_string(&config_path) | ||
| .with_context(|| format!("Failed to read config file: {}", config_path.display()))?; | ||
|
|
||
| let config: Config = toml::from_str(&contents) | ||
| let mut config: Config = toml::from_str(&contents) | ||
| .with_context(|| format!("Failed to parse config file: {}", config_path.display()))?; | ||
|
|
||
| config | ||
| .ignored_extensions | ||
| .iter_mut() | ||
| .for_each(|ext| *ext = normalize_extension(ext)); | ||
| config | ||
| .only_extensions | ||
| .iter_mut() | ||
| .for_each(|ext| *ext = normalize_extension(ext)); | ||
|
|
||
| Ok(config) | ||
| } | ||
|
|
||
|
|
@@ -213,6 +232,22 @@ impl Config { | |
| self.excluded_paths.push(exclude.clone()); | ||
| } | ||
| } | ||
|
|
||
| // Add CLI ignored extensions | ||
| for ext in &options.ignore_ext { | ||
| let ext_lower = normalize_extension(ext); | ||
| if !self.ignored_extensions.contains(&ext_lower) { | ||
| self.ignored_extensions.push(ext_lower); | ||
| } | ||
| } | ||
|
|
||
| // Add CLI only-ext filters | ||
| for ext in &options.only_ext { | ||
| let ext_lower = normalize_extension(ext); | ||
| if !self.only_extensions.contains(&ext_lower) { | ||
| self.only_extensions.push(ext_lower); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| /// Get the base path for scanning | ||
|
|
@@ -228,6 +263,29 @@ impl Config { | |
| self.min_large_size_mb * 1024 * 1024 | ||
| } | ||
|
|
||
| /// Check if a file should be skipped based on extension filters. | ||
| /// Handles both --ignore-ext (exclusion) and --only-ext (inclusion) logic. | ||
| pub fn should_skip_extension(&self, path: &std::path::Path) -> bool { | ||
| if self.ignored_extensions.is_empty() && self.only_extensions.is_empty() { | ||
| return false; | ||
| } | ||
|
|
||
| let ext = match path.extension() { | ||
| Some(e) => e.to_string_lossy().to_lowercase(), | ||
| None => return !self.only_extensions.is_empty(), | ||
| }; | ||
|
|
||
| if self.ignored_extensions.iter().any(|ignored| ignored == &ext) { | ||
| return true; | ||
| } | ||
|
|
||
| if !self.only_extensions.is_empty() { | ||
| return !self.only_extensions.iter().any(|only| only == &ext); | ||
| } | ||
|
|
||
| false | ||
| } | ||
|
|
||
| /// Check if a path should be excluded | ||
| pub fn is_excluded(&self, path: &std::path::Path) -> bool { | ||
| let path_str = path.to_string_lossy(); | ||
|
|
@@ -289,6 +347,10 @@ fn parse_size_mb(s: &str) -> Option<u64> { | |
| s.parse::<u64>().ok() | ||
| } | ||
|
|
||
| fn normalize_extension(ext: &str) -> String { | ||
| ext.trim_start_matches('.').to_lowercase() | ||
| } | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Missing whitespace trim causes silent filter failuresMedium Severity · Logic Bug
|
||
|
|
||
| #[cfg(test)] | ||
| mod tests { | ||
| use super::*; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -103,6 +103,11 @@ impl Scanner for LargeFilesScanner { | |
| continue; | ||
| } | ||
|
|
||
| // Skip based on extension filters | ||
| if config.should_skip_extension(path) { | ||
| continue; | ||
| } | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Extension filtering inconsistently applied across file scannersLow Severity · Logic Bug
Additional Locations (2) |
||
|
|
||
| // Skip hidden files | ||
| if let Some(name) = path.file_name() { | ||
| if name.to_string_lossy().starts_with('.') { | ||
|
|
||


Uh oh!
There was an error while loading. Please reload this page.