use crate::cli::Config;
use crate::errors::ClineupError;
use glob::glob;
use log::debug;
use log::warn;
use std::fs;
use std::path::Path;
use std::path::PathBuf;
pub fn is_allowed_extension(
entry: &PathBuf,
extensions: &Option<Vec<String>>,
exclude_extensions: &Option<Vec<String>>,
) -> bool {
let extension = match entry.extension() {
Some(ext) => ext.to_string_lossy().to_ascii_lowercase().to_string(),
None => return false,
};
if let Some(exts) = extensions {
if !exts.contains(&extension) {
debug!(
"File extension \"{}\" of {:?} is not in the allowed list",
extension, entry
);
return false;
}
}
if let Some(exclude_exts) = exclude_extensions {
if exclude_exts.contains(&extension) {
debug!("File extension {} is in the excluded list", extension);
return false;
}
}
true
}
pub fn is_allowed_size(
entry: &PathBuf,
size_lower: &Option<u64>,
size_greater: &Option<u64>,
) -> Result<bool, ClineupError> {
let metadata = fs::metadata(entry)?;
if let Some(size_lt) = size_lower {
if metadata.len() > *size_lt {
debug!("File size is greater than {size_lt}");
return Ok(false);
}
}
if let Some(size_gt) = size_greater {
if metadata.len() < *size_gt {
debug!("File size is lower than {size_gt}");
return Ok(false);
}
}
Ok(true)
}
fn get_glob_pattern(source: &str, recursive: &bool) -> PathBuf {
let mut source_path = Path::new(source).to_path_buf();
if *recursive {
source_path = source_path.join("**/*");
} else {
source_path = source_path.join("*");
}
source_path
}
pub struct FileIterator<'a> {
entries: glob::Paths,
config: &'a Config,
}
impl<'a> FileIterator<'a> {
pub fn new(config: &'a Config) -> Self {
let source_path = get_glob_pattern(&config.source, &config.recursive);
let entries = glob(&source_path.to_string_lossy()).unwrap_or_else(|_| {
panic!(
"Failed to iterate through source pattern {}",
source_path.display()
)
});
FileIterator { entries, config }
}
}
impl<'a> Iterator for FileIterator<'a> {
type Item = PathBuf;
fn next(&mut self) -> Option<Self::Item> {
for entry in self.entries.by_ref() {
match entry {
Err(err) => {
warn!("Unable to get entry: {:?}", err);
continue;
}
Ok(entry) => {
if entry.is_file() {
if let Some(include_regex) = &self.config.include_regex {
if !include_regex.is_match(&entry.to_string_lossy()) {
continue;
}
}
if let Some(exclude) = &self.config.exclude_regex {
if exclude.is_match(&entry.to_string_lossy()) {
continue;
}
}
if !is_allowed_extension(
&entry,
&self.config.extensions,
&self.config.exclude_extensions,
) {
continue;
}
let _is_allowed_size = is_allowed_size(
&entry,
&self.config.size_lower,
&self.config.size_greater,
);
match _is_allowed_size {
Ok(allowed) => {
if !allowed {
continue;
}
}
Err(err) => {
warn!("Unable to check file size: {:?}", err);
continue;
}
}
return Some(entry);
}
}
}
}
None
}
}