libscilo/fs/mod.rs
1use std::{
2 iter::{Filter, FilterMap},
3 path::{Path, PathBuf},
4};
5use walkdir::{DirEntry, Error, IntoIter, WalkDir};
6
7/// A helper function to set up a directory walker within a given directory.
8///
9/// This ignores symlinks.
10/// This also guarantees that the entries will be walked over in an order, sorted by file name.
11/// The signature on this function is complicated because of the functional implementation.
12pub(crate) fn directory_walker(
13 path: &Path,
14 ignored: &Vec<PathBuf>,
15) -> Filter<
16 Filter<
17 FilterMap<IntoIter, impl FnMut(Result<DirEntry, Error>) -> Option<DirEntry>>,
18 impl FnMut(&DirEntry) -> bool,
19 >,
20 impl FnMut(&DirEntry) -> bool,
21> {
22 WalkDir::new(path)
23 .max_depth(1)
24 .min_depth(1)
25 .sort_by(|a, b| a.file_name().cmp(b.file_name()))
26 .into_iter()
27 .filter_map(|e| e.ok())
28 .filter(|e| match e.metadata() {
29 Ok(meta) => meta.is_dir(),
30 Err(_) => false,
31 })
32 // We use `.iter().any()` instead of `.contains()` since `PathBuf`
33 // implements `PartialEq<Path>` and we don't have to deal with pointers.
34 // Also, the `move` forces the closure to take ownership of `ignored_abs`.
35 .filter(move |dir| !ignored.iter().any(|i| i == dir.path()))
36}