diff --git a/src/uucore/src/lib/mods/version_cmp.rs b/src/uucore/src/lib/mods/version_cmp.rs index 99b8c8b402c..828b7f2a668 100644 --- a/src/uucore/src/lib/mods/version_cmp.rs +++ b/src/uucore/src/lib/mods/version_cmp.rs @@ -106,7 +106,7 @@ pub fn version_cmp(mut a: &str, mut b: &str) -> Ordering { // 1. Compare leading non-numerical part // 2. Compare leading numerical part // 3. Repeat - loop { + while !a.is_empty() || !b.is_empty() { let a_numerical_start = a.find(|c: char| c.is_ascii_digit()).unwrap_or(a.len()); let b_numerical_start = b.find(|c: char| c.is_ascii_digit()).unwrap_or(b.len()); @@ -139,12 +139,9 @@ pub fn version_cmp(mut a: &str, mut b: &str) -> Ordering { a = &a[a_numerical_end..]; b = &b[b_numerical_end..]; - - if a.is_empty() && b.is_empty() { - // Default to the lexical comparison. - return str_cmp; - } } + + Ordering::Equal } #[cfg(test)] @@ -229,14 +226,14 @@ mod tests { // Leading zeroes assert_eq!( version_cmp("012", "12"), - Ordering::Less, - "A single leading zero can make a difference" + Ordering::Equal, + "A single leading zero does not make a difference" ); assert_eq!( version_cmp("000800", "0000800"), - Ordering::Greater, - "Leading number of zeroes is used even if both non-zero number of zeros" + Ordering::Equal, + "Multiple leading zeros do not make a difference" ); // Numbers and other characters combined @@ -280,14 +277,8 @@ mod tests { assert_eq!( version_cmp("aa10aa0022", "aa010aa022"), - Ordering::Greater, - "The leading zeroes of the first number has priority." - ); - - assert_eq!( - version_cmp("aa10aa0022", "aa10aa022"), - Ordering::Less, - "The leading zeroes of other numbers than the first are used." + Ordering::Equal, + "Test multiple numeric values with leading zeros" ); assert_eq!( @@ -307,7 +298,7 @@ mod tests { assert_eq!( version_cmp("aa2000000000000000000000bb", "aa002000000000000000000000bb"), - Ordering::Greater, + Ordering::Equal, "Leading zeroes for numbers larger than u64::MAX are \ handled correctly without crashing" ); diff --git a/tests/by-util/test_ls.rs b/tests/by-util/test_ls.rs index ad2c6424f69..f376cf53d8c 100644 --- a/tests/by-util/test_ls.rs +++ b/tests/by-util/test_ls.rs @@ -2312,56 +2312,15 @@ fn test_ls_version_sort() { let scene = TestScenario::new(util_name!()); let at = &scene.fixtures; for filename in [ - "a2", - "b1", - "b20", - "a1.4", - "a1.40", - "b3", - "b11", - "b20b", - "b20a", - "a100", - "a1.13", - "aa", - "a1", - "aaa", - "a1.00000040", - "abab", - "ab", - "a01.40", - "a001.001", - "a01.0000001", - "a01.001", - "a001.01", + "a2", "b1", "b20", "a1.4", "b3", "b11", "b20b", "b20a", "a100", "a1.13", "aa", "a1", "aaa", + "abab", "ab", "a01.40", "a001.001", ] { at.touch(filename); } let mut expected = vec![ - "a1", - "a001.001", - "a001.01", - "a01.0000001", - "a01.001", - "a1.4", - "a1.13", - "a01.40", - "a1.00000040", - "a1.40", - "a2", - "a100", - "aa", - "aaa", - "ab", - "abab", - "b1", - "b3", - "b11", - "b20", - "b20a", - "b20b", - "", // because of '\n' at the end of the output + "a1", "a001.001", "a1.4", "a1.13", "a01.40", "a2", "a100", "aa", "aaa", "ab", "abab", "b1", + "b3", "b11", "b20", "b20a", "b20b", "", // because of '\n' at the end of the output ]; let result = scene.ucmd().arg("-1v").succeeds(); diff --git a/tests/by-util/test_sort.rs b/tests/by-util/test_sort.rs index e66a405abbb..0c8af8969f2 100644 --- a/tests/by-util/test_sort.rs +++ b/tests/by-util/test_sort.rs @@ -134,6 +134,25 @@ fn test_version_empty_lines() { test_helper("version-empty-lines", &["-V", "--version-sort"]); } +#[test] +fn test_version_sort_unstable() { + new_ucmd!() + .arg("--sort=version") + .pipe_in("0.1\n0.02\n0.2\n0.002\n0.3\n") + .succeeds() + .stdout_is("0.1\n0.002\n0.02\n0.2\n0.3\n"); +} + +#[test] +fn test_version_sort_stable() { + new_ucmd!() + .arg("--stable") + .arg("--sort=version") + .pipe_in("0.1\n0.02\n0.2\n0.002\n0.3\n") + .succeeds() + .stdout_is("0.1\n0.02\n0.2\n0.002\n0.3\n"); +} + #[test] fn test_human_numeric_whitespace() { test_helper(