use std::collections::HashSet;
use crate::core::rclone::RcloneCommand as _;
use crate::core::rclone::command::Lsjson;
pub(crate) async fn list_existing_filenames(destination: &str) -> Result<HashSet<String>, String> {
let entries = (Lsjson {
path: destination.to_string(),
job: "transform",
..Default::default()
})
.run()
.await?;
Ok(entries.into_iter().map(|entry| entry.name).collect())
}
pub(crate) async fn list_source_relative_paths(
source: &str,
extension: &str,
) -> Result<Vec<String>, String> {
let entries = (Lsjson {
path: source.to_string(),
recursive: true,
include_extension: Some(extension.to_string()),
job: "transform",
})
.run()
.await?;
Ok(entries.into_iter().map(|entry| entry.path).collect())
}
#[cfg(test)]
mod tests {
use super::*;
async fn check_rclone_available() -> Result<(), String> {
crate::core::rclone::check_available().await
}
#[tokio::test]
async fn list_existing_filenames_lists_files_present_in_a_local_directory() {
if check_rclone_available().await.is_err() {
eprintln!("skipping: rclone not found on PATH");
return;
}
let dir = tempfile::tempdir().unwrap();
std::fs::write(
dir.path()
.join("2021-08-20_Delivery_Status_Notification_(Failure)_1.png"),
b"png bytes",
)
.unwrap();
std::fs::write(dir.path().join("plain.jpg"), b"jpeg bytes").unwrap();
let names = list_existing_filenames(dir.path().to_str().unwrap())
.await
.unwrap();
assert!(names.contains("2021-08-20_Delivery_Status_Notification_(Failure)_1.png"));
assert!(names.contains("plain.jpg"));
assert_eq!(names.len(), 2);
}
#[tokio::test]
async fn list_existing_filenames_returns_empty_for_a_destination_that_does_not_exist_yet() {
if check_rclone_available().await.is_err() {
eprintln!("skipping: rclone not found on PATH");
return;
}
let dir = tempfile::tempdir().unwrap();
let missing = dir.path().join("does-not-exist-yet");
let names = list_existing_filenames(missing.to_str().unwrap())
.await
.unwrap();
assert!(names.is_empty());
}
#[tokio::test]
async fn list_source_relative_paths_lists_nested_files_matching_the_extension() {
if check_rclone_available().await.is_err() {
eprintln!("skipping: rclone not found on PATH");
return;
}
let dir = tempfile::tempdir().unwrap();
std::fs::create_dir_all(dir.path().join("screenshots")).unwrap();
std::fs::write(dir.path().join("screenshots/img.png"), b"png bytes").unwrap();
std::fs::write(dir.path().join("notes.txt"), b"not a png").unwrap();
let paths = list_source_relative_paths(dir.path().to_str().unwrap(), "png")
.await
.unwrap();
assert_eq!(paths, vec!["screenshots/img.png".to_string()]);
}
#[tokio::test]
async fn list_source_relative_paths_returns_empty_for_a_source_that_does_not_exist_yet() {
if check_rclone_available().await.is_err() {
eprintln!("skipping: rclone not found on PATH");
return;
}
let dir = tempfile::tempdir().unwrap();
let missing = dir.path().join("does-not-exist-yet");
let paths = list_source_relative_paths(missing.to_str().unwrap(), "png")
.await
.unwrap();
assert!(paths.is_empty());
}
}