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}