use std::{ fs::{self, File}, io::{self, Read}, path::{Path, PathBuf}, process::Command, }; use assert_cmd::{assert::OutputAssertExt, cargo::CommandCargoExt}; use tempfile::tempdir; #[test] fn from_empty_dst() { phorg::tracing_init_tests(tracing::Level::DEBUG); let exe = env!("CARGO_PKG_NAME"); let src = PathBuf::from("tests/data/src"); let dst = tempdir().unwrap(); let dst = dst.path(); assert!(file_paths_sorted(dst).is_empty()); let mut cmd = Command::cargo_bin(exe).unwrap(); cmd.arg(&src).arg(&dst).arg("copy"); cmd.assert().success(); let foo_src = "foo.jpg"; let foo_src_path = src.join(foo_src); let foo_dst = format!( "img/2000/12/27/2000-12-27--06:47:01--{}.jpg", hash(&foo_src_path) ); let foo_dst_path = dst.join(foo_dst); let bar_src = "bar.jpg"; let bar_src_path = src.join(bar_src); let bar_dst = format!( "img/2010/01/31/2010-01-31--17:35:49--{}.jpg", hash(&bar_src_path) ); let bar_dst_path = dst.join(bar_dst); let baz_src = "baz.jpg"; let baz_src_path = src.join(baz_src); let baz_dst = format!( "img/2022/10/03/2022-10-03--17:52:16--{}.jpg", hash(&baz_src_path) ); let baz_dst_path = dst.join(baz_dst); assert_eq!( &vec![ &bar_src_path, &baz_src_path, &foo_src_path, &src.join("make") ], &file_paths_sorted(&src).iter().collect::>() ); assert_eq!( &vec![&foo_dst_path, &bar_dst_path, &baz_dst_path][..], &file_paths_sorted(&dst).iter().collect::>() ); assert!(files_eq(foo_src_path, foo_dst_path).unwrap()); assert!(files_eq(bar_src_path, bar_dst_path).unwrap()); } fn hash(path: &Path) -> String { format!( "{}:{}", phorg::hash::Hash::Crc32.name(), phorg::hash::Hash::Crc32.digest(path).unwrap() ) } fn file_paths_sorted(root: &Path) -> Vec { let mut paths: Vec = phorg::files::FilePaths::find(&root).collect(); paths.sort(); paths } fn files_eq>(path_a: P, path_b: P) -> io::Result { const CHUNK_SIZE: usize = 8; let path_a = path_a.as_ref(); let path_b = path_b.as_ref(); let size_a = fs::metadata(path_a)?.len(); let size_b = fs::metadata(path_b)?.len(); if size_a != size_b { return Ok(false); } let mut file_a = File::open(path_a)?; let mut file_b = File::open(path_b)?; let mut buff_a = [0; CHUNK_SIZE]; let mut buff_b = [0; CHUNK_SIZE]; loop { let n_a = file_a.read(&mut buff_a)?; let n_b = file_b.read(&mut buff_b)?; let chunk_a = &buff_a[..n_a]; let chunk_b = &buff_b[..n_b]; if n_a != n_b { return Ok(false); } if chunk_a != chunk_b { return Ok(false); } if n_a == 0 { assert_eq!(n_b, 0); return Ok(true); } } }