proplate_core/
fs.rs

1use std::{
2  fs,
3  path::{Path, PathBuf},
4};
5
6use self::walk::{walk_dir, walk_dir_skip};
7
8pub mod walk;
9
10// Recursively copies dir entries to another
11pub 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
31// Remove file/dir recursively
32pub 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
46/// Updates the provided file content
47pub 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}