Mercurial > hg-stable
changeset 43851:4f1543a2f5c3
rust-hg-path: add method to get part of a path relative to a prefix
This will be used in the next patch in this series.
Differential Revision: https://phab.mercurial-scm.org/D7526
author | Raphaël Gomès <rgomes@octobus.net> |
---|---|
date | Fri, 29 Nov 2019 17:24:40 +0100 |
parents | 1bb4e9b02984 |
children | 542c8b277261 |
files | rust/hg-core/src/utils/hg_path.rs |
diffstat | 1 files changed, 49 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/rust/hg-core/src/utils/hg_path.rs Fri Nov 29 18:33:56 2019 +0100 +++ b/rust/hg-core/src/utils/hg_path.rs Fri Nov 29 17:24:40 2019 +0100 @@ -112,6 +112,9 @@ pub fn contains(&self, other: u8) -> bool { self.inner.contains(&other) } + pub fn starts_with(&self, needle: impl AsRef<HgPath>) -> bool { + self.inner.starts_with(needle.as_ref().as_bytes()) + } pub fn join<T: ?Sized + AsRef<HgPath>>(&self, other: &T) -> HgPathBuf { let mut inner = self.inner.to_owned(); if inner.len() != 0 && inner.last() != Some(&b'/') { @@ -120,6 +123,21 @@ inner.extend(other.as_ref().bytes()); HgPathBuf::from_bytes(&inner) } + /// Given a base directory, returns the slice of `self` relative to the + /// base directory. If `base` is not a directory (does not end with a + /// `b'/'`), returns `None`. + pub fn relative_to(&self, base: impl AsRef<HgPath>) -> Option<&HgPath> { + let base = base.as_ref(); + if base.is_empty() { + return Some(self); + } + let is_dir = base.as_bytes().ends_with(b"/"); + if is_dir && self.starts_with(base) { + Some(HgPath::new(&self.inner[base.len()..])) + } else { + None + } + } /// Checks for errors in the path, short-circuiting at the first one. /// This generates fine-grained errors useful for debugging. /// To simply check if the path is valid during tests, use `is_valid`. @@ -412,4 +430,35 @@ let path = HgPathBuf::from_bytes(b"a").join(HgPath::new(b"/b")); assert_eq!(b"a//b", path.as_bytes()); } + + #[test] + fn test_relative_to() { + let path = HgPath::new(b""); + let base = HgPath::new(b""); + assert_eq!(Some(path), path.relative_to(base)); + + let path = HgPath::new(b"path"); + let base = HgPath::new(b""); + assert_eq!(Some(path), path.relative_to(base)); + + let path = HgPath::new(b"a"); + let base = HgPath::new(b"b"); + assert_eq!(None, path.relative_to(base)); + + let path = HgPath::new(b"a/b"); + let base = HgPath::new(b"a"); + assert_eq!(None, path.relative_to(base)); + + let path = HgPath::new(b"a/b"); + let base = HgPath::new(b"a/"); + assert_eq!(Some(HgPath::new(b"b")), path.relative_to(base)); + + let path = HgPath::new(b"nested/path/to/b"); + let base = HgPath::new(b"nested/path/"); + assert_eq!(Some(HgPath::new(b"to/b")), path.relative_to(base)); + + let path = HgPath::new(b"ends/with/dir/"); + let base = HgPath::new(b"ends/"); + assert_eq!(Some(HgPath::new(b"with/dir/")), path.relative_to(base)); + } }