1use std::{
2 fs,
3 path::{Path, PathBuf},
4};
5
6use self::walk::{walk_dir, walk_dir_skip};
7
8pub mod walk;
9
10pub fn copy_fdir(entry: &Path, dest: &Path, except: Option<Vec<PathBuf>>) -> std::io::Result<()> {
12 fs::create_dir_all(dest)?;
13 for (file, filename) in walk_dir_skip(entry, except.unwrap_or_default())? {
14 let to = dest.join(&filename);
15 if let Some(parent) = to.parent() {
16 fs::create_dir_all(&parent)?;
17 }
18 fs::copy(&file, &to)?;
19 }
20 Ok(())
21}
22
23pub fn map_fdir(path: &Path, f: impl Fn(&str) -> String) -> std::io::Result<()> {
24 for (file, _) in walk_dir(path)? {
25 let content = fs::read_to_string(&file)?;
26 fs::write(&file, f(content.as_str()))?;
27 }
28 Ok(())
29}
30
31pub fn remove_fdir(path: &Path) -> std::io::Result<()> {
33 if !path.exists() {
34 return Ok(());
35 }
36
37 if path.is_file() {
38 fs::remove_file(path)?
39 } else {
40 fs::remove_dir_all(path)?
41 }
42
43 Ok(())
44}
45
46pub fn map_file(path: &Path, f: impl Fn(&str) -> String) -> std::io::Result<()> {
48 let content = fs::read_to_string(path)?;
49 fs::write(path, f(&content))
50}
51
52pub fn is_dir_superset(dir1: &Path, dir2: &Path) -> std::io::Result<bool> {
53 for (file, relative) in walk_dir(dir1)? {
54 let a = fs::read_to_string(&file)?;
55 let b = fs::read_to_string(dir2.join(&relative))?;
56 if a != b {
57 return Ok(false);
58 }
59 }
60 Ok(true)
61}
62
63#[macro_export]
64macro_rules! join_path {
65 ($($path:expr),*) => ({
66 let mut buf = PathBuf::new();
67 $(
68 buf.push($path);
69 )*
70 buf.canonicalize().unwrap_or(buf)
71 })
72}