use std::path::{Path, PathBuf};
use super::format::InputFileType;
use crate::core::data::collect_files;
pub(crate) struct PendingFile {
pub relative_path: String,
pub absolute_path: PathBuf,
}
fn relative_path_string(base: &Path, path: &Path) -> Option<String> {
let relative = path.strip_prefix(base).ok()?;
let components: Vec<&str> = relative
.components()
.filter_map(|c| c.as_os_str().to_str())
.collect();
if components.is_empty() {
return None;
}
Some(components.join("/"))
}
pub(crate) fn gather_pending(
source_dir: &Path,
input_file_type: InputFileType,
) -> Result<Vec<PendingFile>, String> {
let expected_extension = input_file_type.extension();
let mut pending = Vec::new();
for absolute_path in collect_files(source_dir)? {
let Some(relative_path) = relative_path_string(source_dir, &absolute_path) else {
continue;
};
let actual_extension = absolute_path
.extension()
.and_then(|ext| ext.to_str())
.map(|ext| ext.to_ascii_lowercase());
if actual_extension.as_deref() != Some(expected_extension) {
tracing::warn!(
path = %absolute_path.display(),
expected = expected_extension,
"transform: found an unexpected extension under source/, skipping"
);
continue;
}
pending.push(PendingFile {
relative_path,
absolute_path,
});
}
Ok(pending)
}
#[cfg(test)]
mod tests {
use std::fs;
use super::*;
#[test]
fn gather_pending_filters_by_extension() {
let dir = tempfile::tempdir().unwrap();
let source_dir = dir.path().join("source");
fs::create_dir_all(&source_dir).unwrap();
fs::write(source_dir.join("a.png"), b"a").unwrap();
fs::write(source_dir.join("stray.txt"), b"not a png").unwrap();
let pending = gather_pending(&source_dir, InputFileType::Png).unwrap();
assert_eq!(pending.len(), 1);
assert_eq!(pending[0].relative_path, "a.png");
}
#[test]
fn gather_pending_includes_a_nested_relative_path() {
let dir = tempfile::tempdir().unwrap();
let source_dir = dir.path().join("source");
fs::create_dir_all(source_dir.join("screenshots")).unwrap();
fs::write(source_dir.join("screenshots/img.heic"), b"x").unwrap();
let pending = gather_pending(&source_dir, InputFileType::Heic).unwrap();
assert_eq!(pending.len(), 1);
assert_eq!(pending[0].relative_path, "screenshots/img.heic");
}
#[test]
fn gather_pending_filters_by_extension_for_a_video_input_kind() {
let dir = tempfile::tempdir().unwrap();
let source_dir = dir.path().join("source");
fs::create_dir_all(&source_dir).unwrap();
fs::write(source_dir.join("a.mp4"), b"a").unwrap();
fs::write(source_dir.join("stray.mov"), b"not an mp4").unwrap();
let pending = gather_pending(&source_dir, InputFileType::Mp4).unwrap();
assert_eq!(pending.len(), 1);
assert_eq!(pending[0].relative_path, "a.mp4");
}
#[test]
fn gather_pending_includes_every_matching_file_regardless_of_prior_state() {
let dir = tempfile::tempdir().unwrap();
let source_dir = dir.path().join("source");
fs::create_dir_all(&source_dir).unwrap();
fs::write(source_dir.join("a.png"), b"a").unwrap();
fs::write(source_dir.join("b.png"), b"b").unwrap();
let pending = gather_pending(&source_dir, InputFileType::Png).unwrap();
assert_eq!(pending.len(), 2);
}
}