diff --git a/crates/util/src/paths.rs b/crates/util/src/paths.rs index 90b95f2c7b..02e3ac59be 100644 --- a/crates/util/src/paths.rs +++ b/crates/util/src/paths.rs @@ -433,6 +433,38 @@ mod tests { ); } + #[test] + fn compare_paths_case_semi_sensitive() { + let mut paths = vec![ + (Path::new("test_DIRS"), false), + (Path::new("test_DIRS/foo_1"), true), + (Path::new("test_DIRS/foo_2"), true), + (Path::new("test_DIRS/bar"), true), + (Path::new("test_DIRS/BAR"), true), + (Path::new("test_dirs"), false), + (Path::new("test_dirs/foo_1"), true), + (Path::new("test_dirs/foo_2"), true), + (Path::new("test_dirs/bar"), true), + (Path::new("test_dirs/BAR"), true), + ]; + paths.sort_by(|&a, &b| compare_paths(a, b)); + assert_eq!( + paths, + vec![ + (Path::new("test_dirs"), false), + (Path::new("test_dirs/bar"), true), + (Path::new("test_dirs/BAR"), true), + (Path::new("test_dirs/foo_1"), true), + (Path::new("test_dirs/foo_2"), true), + (Path::new("test_DIRS"), false), + (Path::new("test_DIRS/bar"), true), + (Path::new("test_DIRS/BAR"), true), + (Path::new("test_DIRS/foo_1"), true), + (Path::new("test_DIRS/foo_2"), true), + ] + ); + } + #[test] fn path_with_position_parse_posix_path() { // Test POSIX filename edge cases diff --git a/crates/util/src/util.rs b/crates/util/src/util.rs index 1330c3f749..bd87e213f8 100644 --- a/crates/util/src/util.rs +++ b/crates/util/src/util.rs @@ -659,15 +659,22 @@ impl<'a> NumericPrefixWithSuffix<'a> { Self(prefix, remainder) } } + +/// When dealing with equality, we need to consider the case of the strings to achieve strict equality +/// to handle cases like "a" < "A" instead of "a" == "A". impl Ord for NumericPrefixWithSuffix<'_> { fn cmp(&self, other: &Self) -> Ordering { match (self.0, other.0) { - (None, None) => UniCase::new(self.1).cmp(&UniCase::new(other.1)), + (None, None) => UniCase::new(self.1) + .cmp(&UniCase::new(other.1)) + .then_with(|| self.1.cmp(other.1).reverse()), (None, Some(_)) => Ordering::Greater, (Some(_), None) => Ordering::Less, - (Some(a), Some(b)) => a - .cmp(&b) - .then_with(|| UniCase::new(self.1).cmp(&UniCase::new(other.1))), + (Some(a), Some(b)) => a.cmp(&b).then_with(|| { + UniCase::new(self.1) + .cmp(&UniCase::new(other.1)) + .then_with(|| self.1.cmp(other.1).reverse()) + }), } } }