#![allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)]
use fren_date::{merge_directories, unique_file_name};
use std::fs;
use std::path::Path;
use tempfile::TempDir;
fn touch(path: impl AsRef<Path>) {
let path = path.as_ref();
if let Some(parent) = path.parent() {
fs::create_dir_all(parent).unwrap();
}
fs::write(path, b"").unwrap();
}
#[test]
fn test_unique_file_name_numeric_index() {
let tmp = TempDir::new().unwrap();
let path = tmp.path().join("file.txt");
assert_eq!(unique_file_name(&path), path);
fs::write(&path, b"").unwrap();
let first = path.with_file_name("file_Copy.txt");
assert_eq!(unique_file_name(&path), first);
fs::write(&first, b"").unwrap();
let second = path.with_file_name("file_Copy1.txt");
assert_eq!(unique_file_name(&first), second);
fs::write(&second, b"").unwrap();
let third = path.with_file_name("file_Copy2.txt");
assert_eq!(unique_file_name(&second), third);
}
#[test]
fn test_merge_directories_full() {
let tmp = TempDir::new().unwrap();
let target = tmp.path();
touch(target.join("2020").join("12").join("one.txt"));
touch(target.join("2020").join("root.txt"));
let other = target.join("other");
touch(other.join("2020").join("root_Copy.txt"));
touch(other.join("2020").join("12").join("one.txt"));
touch(other.join("2020").join("12").join("two.txt"));
touch(other.join("2021").join("01").join("three.txt"));
let another = target.join("another");
touch(another.join("2020").join("12").join("one.txt"));
touch(another.join("2020").join("12").join("two.txt"));
touch(another.join("2020").join("root_Copy.txt"));
merge_directories(target, &[other.as_ref(), another.as_ref()], false).unwrap();
let mut actual: Vec<String> = walk(target);
actual.sort();
actual.retain(|p| !p.starts_with("other") && !p.starts_with("another"));
let expected = vec![
"2020/12/one.txt",
"2020/12/one_Copy.txt",
"2020/12/one_Copy1.txt",
"2020/12/two.txt",
"2020/12/two_Copy.txt",
"2020/root.txt",
"2020/root_Copy.txt",
"2020/root_Copy1.txt",
"2021/01/three.txt",
];
assert_eq!(actual, expected);
}
fn walk(root: &Path) -> Vec<String> {
let mut out = Vec::new();
walk_inner(root, root, &mut out);
out
}
fn walk_inner(root: &Path, current: &Path, out: &mut Vec<String>) {
for entry in fs::read_dir(current).unwrap() {
let entry = entry.unwrap();
let p = entry.path();
if p.is_dir() {
walk_inner(root, &p, out);
} else {
out.push(p.strip_prefix(root).unwrap().to_string_lossy().into_owned());
}
}
}
#[test]
fn merge_dry_run_makes_no_changes() {
let tmp = TempDir::new().unwrap();
let target = tmp.path();
touch(target.join("a.txt"));
let source = target.join("src");
touch(source.join("a.txt"));
let report = merge_directories(target, &[source.as_ref()], true).unwrap();
assert_eq!(report.moved.len(), 1);
assert!(source.join("a.txt").exists());
}
#[test]
fn merge_skips_ds_store() {
let tmp = TempDir::new().unwrap();
let target = tmp.path();
let source = target.join("src");
touch(source.join(".DS_Store"));
touch(source.join("real.txt"));
let report = merge_directories(target, &[source.as_ref()], false).unwrap();
let moved_names: Vec<_> = report
.moved
.iter()
.map(|m| m.from.file_name().unwrap().to_string_lossy().into_owned())
.collect();
assert!(!moved_names.iter().any(|n| n == ".DS_Store"));
assert!(moved_names.iter().any(|n| n == "real.txt"));
}