build_helper/fs/
mod.rs
1use std::fs::Metadata;
3use std::path::Path;
4use std::{fs, io};
5
6#[cfg(test)]
7mod tests;
8
9pub fn ignore_not_found<Op>(mut op: Op) -> io::Result<()>
12where
13 Op: FnMut() -> io::Result<()>,
14{
15 match op() {
16 Ok(()) => Ok(()),
17 Err(e) if e.kind() == io::ErrorKind::NotFound => Ok(()),
18 Err(e) => Err(e),
19 }
20}
21
22#[track_caller]
37pub fn recursive_remove<P: AsRef<Path>>(path: P) -> io::Result<()> {
38 let path = path.as_ref();
39 let metadata = fs::symlink_metadata(path)?;
40 #[cfg(windows)]
41 let is_dir_like = |meta: &fs::Metadata| {
42 use std::os::windows::fs::FileTypeExt;
43 meta.is_dir() || meta.file_type().is_symlink_dir()
44 };
45 #[cfg(not(windows))]
46 let is_dir_like = fs::Metadata::is_dir;
47
48 if is_dir_like(&metadata) {
49 fs::remove_dir_all(path)
50 } else {
51 try_remove_op_set_perms(fs::remove_file, path, metadata)
52 }
53}
54
55fn try_remove_op_set_perms<'p, Op>(mut op: Op, path: &'p Path, metadata: Metadata) -> io::Result<()>
56where
57 Op: FnMut(&'p Path) -> io::Result<()>,
58{
59 match op(path) {
60 Ok(()) => Ok(()),
61 Err(e) if e.kind() == io::ErrorKind::PermissionDenied => {
62 let mut perms = metadata.permissions();
63 perms.set_readonly(false);
64 fs::set_permissions(path, perms)?;
65 op(path)
66 }
67 Err(e) => Err(e),
68 }
69}