Skip to content

Commit d628f76

Browse files
committed
Make two Paths unequal if they differ in trailing slash
1 parent 8a12be7 commit d628f76

File tree

2 files changed

+47
-9
lines changed

2 files changed

+47
-9
lines changed

library/std/src/path.rs

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1738,7 +1738,7 @@ impl ToOwned for Path {
17381738
impl cmp::PartialEq for PathBuf {
17391739
#[inline]
17401740
fn eq(&self, other: &PathBuf) -> bool {
1741-
self.components() == other.components()
1741+
Path::eq(self, other)
17421742
}
17431743
}
17441744

@@ -1756,15 +1756,15 @@ impl cmp::Eq for PathBuf {}
17561756
impl cmp::PartialOrd for PathBuf {
17571757
#[inline]
17581758
fn partial_cmp(&self, other: &PathBuf) -> Option<cmp::Ordering> {
1759-
Some(compare_components(self.components(), other.components()))
1759+
Path::partial_cmp(self, other)
17601760
}
17611761
}
17621762

17631763
#[stable(feature = "rust1", since = "1.0.0")]
17641764
impl cmp::Ord for PathBuf {
17651765
#[inline]
17661766
fn cmp(&self, other: &PathBuf) -> cmp::Ordering {
1767-
compare_components(self.components(), other.components())
1767+
Path::cmp(self, other)
17681768
}
17691769
}
17701770

@@ -2718,6 +2718,14 @@ impl Path {
27182718
let inner = unsafe { Box::from_raw(rw) };
27192719
PathBuf { inner: OsString::from(inner) }
27202720
}
2721+
2722+
fn ends_with_separator(&self) -> bool {
2723+
let components = self.components();
2724+
match components.path.last() {
2725+
None => false,
2726+
Some(byte) => components.is_sep_byte(*byte),
2727+
}
2728+
}
27212729
}
27222730

27232731
#[stable(feature = "rust1", since = "1.0.0")]
@@ -2779,6 +2787,7 @@ impl cmp::PartialEq for Path {
27792787
#[inline]
27802788
fn eq(&self, other: &Path) -> bool {
27812789
self.components() == other.components()
2790+
&& self.ends_with_separator() == other.ends_with_separator()
27822791
}
27832792
}
27842793

@@ -2798,7 +2807,7 @@ impl cmp::Eq for Path {}
27982807
impl cmp::PartialOrd for Path {
27992808
#[inline]
28002809
fn partial_cmp(&self, other: &Path) -> Option<cmp::Ordering> {
2801-
Some(compare_components(self.components(), other.components()))
2810+
Some(Ord::cmp(self, other))
28022811
}
28032812
}
28042813

@@ -2807,6 +2816,7 @@ impl cmp::Ord for Path {
28072816
#[inline]
28082817
fn cmp(&self, other: &Path) -> cmp::Ordering {
28092818
compare_components(self.components(), other.components())
2819+
.then_with(|| self.ends_with_separator().cmp(&other.ends_with_separator()))
28102820
}
28112821
}
28122822

library/std/src/path/tests.rs

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1427,7 +1427,11 @@ pub fn test_compare() {
14271427
let eq = path1 == path2;
14281428
assert!(eq == $eq, "{:?} == {:?}, expected {:?}, got {:?}",
14291429
$path1, $path2, $eq, eq);
1430-
assert!($eq == (hash(path1) == hash(path2)),
1430+
1431+
// They have the same hash if the paths are equal or differ only in
1432+
// trailing separator.
1433+
assert_eq!($eq || $path1.trim_end_matches('/') == $path2.trim_end_matches('/'),
1434+
hash(path1) == hash(path2),
14311435
"{:?} == {:?}, expected {:?}, got {} and {}",
14321436
$path1, $path2, $eq, hash(path1), hash(path2));
14331437

@@ -1480,7 +1484,7 @@ pub fn test_compare() {
14801484
);
14811485

14821486
tc!("foo/", "foo",
1483-
eq: true,
1487+
eq: false,
14841488
starts_with: true,
14851489
ends_with: true,
14861490
relative_from: Some("")
@@ -1532,6 +1536,27 @@ pub fn test_compare() {
15321536
}
15331537
}
15341538

1539+
#[test]
1540+
fn test_trailing_separator() {
1541+
let file = Path::new("tmp/f");
1542+
let dir = Path::new("tmp/f/");
1543+
1544+
assert_ne!(file, dir);
1545+
assert!(file < dir);
1546+
assert_eq!(dir, Path::new("tmp/f//"));
1547+
assert_eq!(file.components(), dir.components());
1548+
1549+
if cfg!(windows) {
1550+
assert_eq!(dir, Path::new(r"tmp\f\"));
1551+
assert_eq!(dir, Path::new(r"tmp\f\\"));
1552+
}
1553+
1554+
let file = file.to_owned();
1555+
let dir = dir.to_owned();
1556+
assert_ne!(file, dir);
1557+
assert!(file < dir);
1558+
}
1559+
15351560
#[test]
15361561
fn test_components_debug() {
15371562
let path = Path::new("/tmp");
@@ -1629,10 +1654,13 @@ fn test_ord() {
16291654
ord!(Less, "1", "2");
16301655
ord!(Less, "/foo/bar", "/foo./bar");
16311656
ord!(Less, "foo/bar", "foo/bar.");
1632-
ord!(Equal, "foo/./bar", "foo/bar/");
1633-
ord!(Equal, "foo/bar", "foo/bar/");
1657+
ord!(Equal, "foo/./bar", "foo/bar");
1658+
ord!(Less, "foo/./bar", "foo/bar/");
1659+
ord!(Equal, "foo/./bar/", "foo/bar/");
1660+
ord!(Less, "foo/bar", "foo/bar/");
16341661
ord!(Equal, "foo/bar", "foo/bar/.");
1635-
ord!(Equal, "foo/bar", "foo/bar//");
1662+
ord!(Less, "foo/bar", "foo/bar//");
1663+
ord!(Equal, "foo/bar/", "foo/bar//");
16361664
}
16371665

16381666
#[bench]

0 commit comments

Comments
 (0)