1use std::fs;
2use std::path::Path;
3
4pub fn move_directory_contents(
26 src_dir: impl AsRef<Path>,
27 dst_dir: impl AsRef<Path>,
28) -> Result<(), std::io::Error> {
29 for dir_entry in fs::read_dir(src_dir.as_ref())? {
30 let dir_entry = dir_entry?;
31 let relative_path = pathdiff::diff_paths(dir_entry.path(), src_dir.as_ref())
32 .ok_or_else(|| std::io::Error::other("std::fs::read_dir unexpectedly returned an entry that is not in the directory that was read."))?;
33
34 fs::rename(dir_entry.path(), dst_dir.as_ref().join(relative_path))?;
35 }
36
37 Ok(())
38}
39
40#[cfg(test)]
41mod test {
42 use std::collections::HashMap;
43 use std::path::PathBuf;
44
45 use tempfile::tempdir;
46
47 use super::*;
48
49 #[test]
50 fn test() {
51 let src_dir = tempdir().unwrap();
52 let dst_dir = tempdir().unwrap();
53
54 let mut test_data = HashMap::new();
55 test_data.insert(PathBuf::from("foo"), String::from("foo"));
56 test_data.insert(PathBuf::from("bar"), String::from("bar"));
57 test_data.insert(PathBuf::from("baz"), String::from("baz"));
58 test_data.insert(
59 PathBuf::from("subdir").join("foo"),
60 String::from("foosubdir"),
61 );
62 test_data.insert(
63 PathBuf::from("subdir")
64 .join("more")
65 .join("more")
66 .join("file.txt"),
67 String::from("Hello World!"),
68 );
69
70 for (path, contents) in &test_data {
71 if let Some(parent_dir) = path.parent() {
72 fs::create_dir_all(src_dir.path().join(parent_dir)).unwrap();
73 }
74
75 fs::write(src_dir.path().join(path), contents).unwrap();
76 }
77
78 move_directory_contents(&src_dir, &dst_dir).unwrap();
79
80 for (path, expected_contents) in &test_data {
81 let actual_contents = fs::read_to_string(dst_dir.path().join(path)).unwrap();
82 assert_eq!(expected_contents, &actual_contents);
83 }
84
85 assert!(src_dir.path().exists());
86
87 assert!(fs::read_dir(src_dir.path()).unwrap().next().is_none());
88 }
89}