diff --git a/src/app/sub.rs b/src/app/sub.rs index 1b06a7a..8fe17e3 100644 --- a/src/app/sub.rs +++ b/src/app/sub.rs @@ -1,10 +1,11 @@ +mod mount_point; + use crate::{ args::Fraction, data_tree::{DataTree, DataTreeReflection}, fs_tree_builder::FsTreeBuilder, get_size::GetSize, json_data::{BinaryVersion, JsonData, SchemaVersion, UnitAndTree}, - mount_point::find_mountpoint, os_string_display::OsStringDisplay, reporter::ParallelReporter, runtime_error::RuntimeError, @@ -12,9 +13,10 @@ use crate::{ status_board::GLOBAL_STATUS_BOARD, visualizer::{BarAlignment, ColumnWidthDistribution, Direction, Visualizer}, }; +use mount_point::find_mount_point; use serde::Serialize; use std::{fs, io::stdout, iter::once, num::NonZeroUsize, path::PathBuf}; -use sysinfo::{DiskKind, Disks}; +use sysinfo::{Disk, DiskKind, Disks}; /// The sub program of the main application. pub struct Sub @@ -74,24 +76,11 @@ where // If one of the files is on HDD, set thread number to 1 let disks = Disks::new_with_refreshed_list(); - if files - .iter() - .filter_map(|file| fs::canonicalize(file).ok()) - .any(|path| { - let mount_points: Vec<_> = disks.iter().map(|disk| disk.mount_point()).collect(); - if let Some(mount_point) = find_mountpoint(&path, &mount_points) { - disks.iter().any(|disk| { - matches!(disk.kind(), DiskKind::HDD) && disk.mount_point() == mount_point - }) - } else { - false - } - }) - { + if detect_hdd_in_files(&disks, &files, |disk| disk.kind()) { rayon::ThreadPoolBuilder::new() .num_threads(1) .build_global() - .unwrap(); + .unwrap_or_else(|_| eprintln!("warning: This program is suboptimal with HDD")); } let mut iter = files @@ -174,3 +163,24 @@ where Ok(()) } } + +fn detect_hdd_in_files( + disks: &[Disk], + files: &[PathBuf], + get_disk_kind: impl Fn(&Disk) -> DiskKind, +) -> bool { + files + .iter() + .filter_map(|file| fs::canonicalize(file).ok()) + .any(|path| { + if let Some(mount_point) = + find_mount_point(&path, disks.iter().map(|disk| disk.mount_point())) + { + disks.iter().any(|disk| { + get_disk_kind(disk) == DiskKind::HDD && disk.mount_point() == mount_point + }) + } else { + false + } + }) +} diff --git a/src/app/sub/mount_point.rs b/src/app/sub/mount_point.rs new file mode 100644 index 0000000..397614e --- /dev/null +++ b/src/app/sub/mount_point.rs @@ -0,0 +1,41 @@ +use std::{ffi::OsStr, path::Path}; + +pub(super) fn find_mount_point<'a>( + path: &Path, + mount_points: impl IntoIterator, +) -> Option<&'a Path> { + mount_points + .into_iter() + .filter(|mnt| path.starts_with(&*mnt.to_string_lossy())) + .max_by_key(|mnt| AsRef::::as_ref(mnt).len()) // Mount points can be nested in each other +} + +#[cfg(test)] +mod tests { + use super::find_mount_point; + use std::path::Path; + + #[test] + fn test_mountpoint() { + let mount_points = [ + Path::new("/"), + Path::new("/home"), + Path::new("/mnt/data"), + Path::new("/mnt/data/repo"), + Path::new("/mnt/repo"), + ]; + + for (path, mount_point) in &[ + ("/etc/fstab", "/"), + ("/home/user", "/home"), + ("/mnt/data/repo/test", "/mnt/data/repo"), + ("/mnt/data/test/test", "/mnt/data/"), + ("/mnt/repo/test/test", "/mnt/repo/"), + ] { + assert_eq!( + find_mount_point(Path::new(path), mount_points).unwrap(), + Path::new(mount_point) + ); + } + } +} diff --git a/src/lib.rs b/src/lib.rs index 84ff2f2..fed11c1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -34,7 +34,6 @@ pub mod data_tree; pub mod fs_tree_builder; pub mod get_size; pub mod json_data; -pub mod mount_point; pub mod os_string_display; pub mod reporter; pub mod size; diff --git a/src/mount_point.rs b/src/mount_point.rs deleted file mode 100644 index 1cf0ba9..0000000 --- a/src/mount_point.rs +++ /dev/null @@ -1,11 +0,0 @@ -use std::path::{Path, PathBuf}; - -pub fn find_mountpoint(path: &Path, mount_points: &[&Path]) -> Option { - let path = path.to_string_lossy(); - - mount_points - .iter() - .filter(|mnt| path.starts_with(&*mnt.to_string_lossy())) - .max_by_key(|mnt| mnt.to_string_lossy().len()) - .map(|mnt| mnt.to_path_buf()) -} diff --git a/tests/find_mountpoint.rs b/tests/find_mountpoint.rs deleted file mode 100644 index 9377823..0000000 --- a/tests/find_mountpoint.rs +++ /dev/null @@ -1,26 +0,0 @@ -use parallel_disk_usage::mount_point::find_mountpoint; -use std::path::Path; - -#[test] -fn test_mountpoint() { - let mount_points = &[ - Path::new("/"), - Path::new("/home"), - Path::new("/mnt/data"), - Path::new("/mnt/data/repo"), - Path::new("/mnt/repo"), - ]; - - for (path, mount_point) in &[ - ("/etc/fstab", "/"), - ("/home/user", "/home"), - ("/mnt/data/repo/test", "/mnt/data/repo"), - ("/mnt/data/test/test", "/mnt/data/"), - ("/mnt/repo/test/test", "/mnt/repo/"), - ] { - assert_eq!( - find_mountpoint(Path::new(path), mount_points).unwrap(), - Path::new(mount_point) - ); - } -}