Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
sosthene-nitrokey committed Apr 12, 2023
1 parent c2d2605 commit 872c25b
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 5 deletions.
36 changes: 31 additions & 5 deletions src/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,11 @@ impl From<ll::lfs_info> for Metadata
}
}

struct RemoveDirAllProgress {
files_removed: usize,
skipped_any: bool,
}

impl<Storage: driver::Storage> Filesystem<'_, Storage> {

pub fn allocate() -> Allocation<Storage> {
Expand Down Expand Up @@ -315,14 +320,21 @@ impl<Storage: driver::Storage> Filesystem<'_, Storage> {
self.remove_dir_all_where(path, &|_| true).map(|_| ())
}

#[cfg(feature = "dir-entry-path")]
pub fn remove_dir_all_where<P>(&self, path: &Path, predicate: &P) -> Result<usize>
/// Returns number of deleted files + whether the directory was fully deleted or not
fn remove_dir_all_where_inner<P>(
&self,
path: &Path,
predicate: &P,
) -> Result<RemoveDirAllProgress>
where
P: Fn(&DirEntry) -> bool,
{
if !path.exists(self) {
debug_now!("no such directory {}, early return", path);
return Ok(0);
return Ok(RemoveDirAllProgress {
files_removed: 0,
skipped_any: false,
});
}
let mut skipped_any = false;
let mut files_removed = 0;
Expand All @@ -345,7 +357,9 @@ impl<Storage: driver::Storage> Filesystem<'_, Storage> {
}
if entry.file_type().is_dir() {
debug_now!("recursing into directory {}", &entry.path());
files_removed += self.remove_dir_all_where(entry.path(), predicate)?;
let progress = self.remove_dir_all_where_inner(entry.path(), predicate)?;
files_removed += progress.files_removed;
skipped_any |= progress.skipped_any;
debug_now!("...back");
}
}
Expand All @@ -356,7 +370,19 @@ impl<Storage: driver::Storage> Filesystem<'_, Storage> {
self.remove_dir(path)?;
debug_now!("..worked");
}
Ok(files_removed)
Ok(RemoveDirAllProgress {
files_removed,
skipped_any,
})
}

#[cfg(feature = "dir-entry-path")]
pub fn remove_dir_all_where<P>(&self, path: &Path, predicate: &P) -> Result<usize>
where
P: Fn(&DirEntry) -> bool,
{
self.remove_dir_all_where_inner(path, predicate)
.map(|progress| progress.files_removed)
}

/// Rename or move a file or directory.
Expand Down
1 change: 1 addition & 0 deletions src/path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use crate::consts;
/// accepts arbitrary C strings), but the assumption makes `AsRef<str>` trivial
/// to implement.
#[derive(PartialEq, Eq)]
#[repr(transparent)]
pub struct Path {
inner: CStr,
}
Expand Down
30 changes: 30 additions & 0 deletions src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use crate::{
Read,
SeekFrom,
},
path::Path,
driver,
};

Expand Down Expand Up @@ -347,6 +348,35 @@ fn test_fancy_open() {
assert_eq!(&buf, b"world");
}

#[test]
fn remove_dir_all_where() {
let mut backend = Ram::default();
let mut storage = RamStorage::new(&mut backend);

Filesystem::format(&mut storage).unwrap();

Filesystem::mount_and_then(&mut storage, |fs| {
fs.write(path!("test_file"), b"some data").unwrap();
fs.create_dir(path!("test_dir")).unwrap();
fs.write(path!("test_dir/test_file"), b"some_inner_data")
.unwrap();
fs.write(path!("test_dir/test_file2"), b"some_inner_data")
.unwrap();
fs.remove_dir_all_where(path!(""), &|entry| {
entry.path() != path!("test_dir/test_file")
})
.unwrap();
assert!(fs.metadata(path!("test_dir/test_file")).unwrap().is_file());
assert_eq!(fs.metadata(path!("test_file")), Err(Error::NoSuchEntry));
assert_eq!(
fs.metadata(path!("test_dir/test_file2")),
Err(Error::NoSuchEntry)
);
Ok(())
})
.unwrap();
}

#[test]
fn attributes() {
let mut backend = Ram::default();
Expand Down

0 comments on commit 872c25b

Please sign in to comment.