summaryrefslogtreecommitdiffstats
path: root/src/common.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/common.rs')
-rw-r--r--src/common.rs24
1 files changed, 16 insertions, 8 deletions
diff --git a/src/common.rs b/src/common.rs
index f5f862e..5eb094e 100644
--- a/src/common.rs
+++ b/src/common.rs
@@ -1,3 +1,4 @@
+use crate::crossdev;
use crate::traverse::{EntryData, Tree, TreeIndex};
use byte_unit::{n_gb_bytes, n_gib_bytes, n_mb_bytes, n_mib_bytes, ByteUnit};
use std::path::PathBuf;
@@ -130,8 +131,8 @@ pub struct WalkOptions {
type WalkDir = jwalk::WalkDirGeneric<((), Option<Result<std::fs::Metadata, jwalk::Error>>)>;
impl WalkOptions {
- pub(crate) fn iter_from_path(&self, path: &Path) -> WalkDir {
- WalkDir::new(path)
+ pub(crate) fn iter_from_path(&self, root: &Path, root_device_id: u64) -> WalkDir {
+ WalkDir::new(root)
.follow_links(false)
.sort(match self.sorting {
TraversalSorting::None => false,
@@ -140,16 +141,23 @@ impl WalkOptions {
.skip_hidden(false)
.process_read_dir({
let ignore_dirs = self.ignore_dirs.clone();
+ let cross_filesystems = self.cross_filesystems;
move |_, _, _, dir_entry_results| {
dir_entry_results.iter_mut().for_each(|dir_entry_result| {
if let Ok(dir_entry) = dir_entry_result {
+ let metadata = dir_entry.metadata();
+
if dir_entry.file_type.is_file() || dir_entry.file_type().is_symlink() {
- dir_entry.client_state = Some(dir_entry.metadata());
- }
- if dir_entry.file_type.is_dir()
- && ignore_dirs.contains(&dir_entry.path())
- {
- dir_entry.read_children_path = None;
+ dir_entry.client_state = Some(metadata);
+ } else if dir_entry.file_type.is_dir() {
+ let ok_for_fs = cross_filesystems
+ || metadata
+ .as_ref()
+ .map(|m| crossdev::is_same_device(root_device_id, m))
+ .unwrap_or(true);
+ if !ok_for_fs || ignore_dirs.contains(&dir_entry.path()) {
+ dir_entry.read_children_path = None;
+ }
}
}
})