summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorandy.boot <bootandy@gmail.com>2024-06-27 23:47:15 +0100
committerandy.boot <bootandy@gmail.com>2024-06-27 23:47:15 +0100
commit1644e67b119073dd1912b127a7bf483a3ef8fe3e (patch)
tree6a4562a461d6c9cd7c22da2fad2a2421a2292d68
parenta06a00188617b3932a9ed62c831fbb98118a9e07 (diff)
fix: total_ordering of sort_by_inodetest
Before sort_by_inode could result in unstable ordering. This change ensures we will always have a reliable total ordering
-rw-r--r--src/dir_walker.rs53
1 files changed, 48 insertions, 5 deletions
diff --git a/src/dir_walker.rs b/src/dir_walker.rs
index c8bddca..cfd016e 100644
--- a/src/dir_walker.rs
+++ b/src/dir_walker.rs
@@ -1,3 +1,4 @@
+use std::cmp::Ordering;
use std::fs;
use std::sync::Arc;
use std::sync::Mutex;
@@ -95,16 +96,20 @@ fn clean_inodes(
fn sort_by_inode(a: &Node, b: &Node) -> std::cmp::Ordering {
// Sorting by inode is quicker than by sorting by name/size
- if let Some(x) = a.inode_device {
- if let Some(y) = b.inode_device {
+ match (a.inode_device, b.inode_device) {
+ (Some(x), Some(y)) => {
if x.0 != y.0 {
- return x.0.cmp(&y.0);
+ x.0.cmp(&y.0)
} else if x.1 != y.1 {
- return x.1.cmp(&y.1);
+ x.1.cmp(&y.1)
+ } else {
+ a.name.cmp(&b.name)
}
}
+ (Some(_), None) => Ordering::Greater,
+ (None, Some(_)) => Ordering::Less,
+ (None, None) => a.name.cmp(&b.name),
}
- a.name.cmp(&b.name)
}
fn ignore_file(entry: &DirEntry, walk_data: &WalkData) -> bool {
@@ -244,6 +249,7 @@ fn walk(dir: PathBuf, walk_data: &WalkData, depth: usize) -> Option<Node> {
}
mod tests {
+
#[allow(unused_imports)]
use super::*;
@@ -281,4 +287,41 @@ mod tests {
assert_eq!(clean_inodes(n.clone(), &mut inodes, true), Some(n.clone()));
assert_eq!(clean_inodes(n.clone(), &mut inodes, true), Some(n.clone()));
}
+
+ #[test]
+ fn test_total_ordering_of_sort_by_inode() {
+ use std::str::FromStr;
+
+ let a = Node {
+ name: PathBuf::from_str("a").unwrap(),
+ size: 0,
+ children: vec![],
+ inode_device: Some((3, 66310)),
+ depth: 0,
+ };
+
+ let b = Node {
+ name: PathBuf::from_str("b").unwrap(),
+ size: 0,
+ children: vec![],
+ inode_device: None,
+ depth: 0,
+ };
+
+ let c = Node {
+ name: PathBuf::from_str("c").unwrap(),
+ size: 0,
+ children: vec![],
+ inode_device: Some((1, 66310)),
+ depth: 0,
+ };
+
+ assert_eq!(sort_by_inode(&a, &b), Ordering::Greater);
+ assert_eq!(sort_by_inode(&a, &c), Ordering::Greater);
+ assert_eq!(sort_by_inode(&c, &b), Ordering::Greater);
+
+ assert_eq!(sort_by_inode(&b, &a), Ordering::Less);
+ assert_eq!(sort_by_inode(&c, &a), Ordering::Less);
+ assert_eq!(sort_by_inode(&b, &c), Ordering::Less);
+ }
}