[PATCH 1 of 2] rust-dirstate: add helper to iterate ancestor paths
Martin von Zweigbergk
martinvonz at google.com
Wed Jul 10 14:36:26 UTC 2019
On Sun, Jun 30, 2019, 04:17 Yuya Nishihara <yuya at tcha.org> wrote:
> # HG changeset patch
> # User Yuya Nishihara <yuya at tcha.org>
> # Date 1561887163 -32400
> # Sun Jun 30 18:32:43 2019 +0900
> # Node ID 72ab74c704053b2212b874a902574fedadad4252
> # Parent 904e0da2e195d2a29977ceccdd25480233c34d7a
> rust-dirstate: add helper to iterate ancestor paths
>
> This is modeled after std::path::Path::ancestors().
>
> find_dirs(b"") yields b"" because Mercurial's util.finddirs() works in that
> way, and the test case for DirsMultiset expects such behavior.
>
That's also how std::path::Path::ancestors() works, it seems.
> diff --git a/rust/hg-core/src/utils/files.rs b/rust/hg-core/src/utils/
> files.rs
> --- a/rust/hg-core/src/utils/files.rs
> +++ b/rust/hg-core/src/utils/files.rs
> @@ -1,3 +1,4 @@
> +use std::iter::FusedIterator;
> use std::path::Path;
>
> pub fn get_path_from_bytes(bytes: &[u8]) -> &Path {
> @@ -17,3 +18,66 @@ pub fn get_path_from_bytes(bytes: &[u8])
>
> Path::new(os_str)
> }
> +
> +/// An iterator over repository path yielding itself and its ancestors.
> +#[derive(Copy, Clone, Debug)]
> +pub struct Ancestors<'a> {
> + next: Option<&'a [u8]>,
> +}
> +
> +impl<'a> Iterator for Ancestors<'a> {
> + // if we had an HgPath type, this would yield &'a HgPath
> + type Item = &'a [u8];
> +
> + fn next(&mut self) -> Option<Self::Item> {
> + let next = self.next;
> + self.next = match self.next {
> + Some(s) if s.is_empty() => None,
> + Some(s) => {
> + let p = s.iter().rposition(|&c| c == b'/').unwrap_or(0);
> + Some(&s[..p])
> + }
> + None => None,
> + };
> + next
> + }
> +}
> +
> +impl<'a> FusedIterator for Ancestors<'a> {}
> +
> +/// Returns an iterator yielding ancestor directories of the given
> repository
> +/// path.
> +///
> +/// The path is separated by '/', and must not start with '/'.
> +///
> +/// The path itself isn't included unless it is b"" (meaning the root
> +/// directory.)
> +pub fn find_dirs<'a>(path: &'a [u8]) -> Ancestors<'a> {
> + let mut dirs = Ancestors { next: Some(path) };
> + if !path.is_empty() {
> + dirs.next(); // skip itself
> + }
> + dirs
> +}
> +
> +#[cfg(test)]
> +mod tests {
> + #[test]
> + fn find_dirs_some() {
> + let mut dirs = super::find_dirs(b"foo/bar/baz");
> + assert_eq!(dirs.next(), Some(b"foo/bar".as_ref()));
> + assert_eq!(dirs.next(), Some(b"foo".as_ref()));
> + assert_eq!(dirs.next(), Some(b"".as_ref()));
> + assert_eq!(dirs.next(), None);
> + assert_eq!(dirs.next(), None);
> + }
> +
> + #[test]
> + fn find_dirs_empty() {
> + // looks weird, but mercurial.util.finddirs(b"") yields b""
> + let mut dirs = super::find_dirs(b"");
> + assert_eq!(dirs.next(), Some(b"".as_ref()));
> + assert_eq!(dirs.next(), None);
> + assert_eq!(dirs.next(), None);
> + }
> +}
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel at mercurial-scm.org
> https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.mercurial-scm.org/pipermail/mercurial-devel/attachments/20190710/5e182218/attachment-0002.html>
More information about the Mercurial-devel
mailing list