<div dir="auto"><div><br><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Sun, Jun 30, 2019, 04:17 Yuya Nishihara <<a href="mailto:yuya@tcha.org">yuya@tcha.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"># HG changeset patch<br>
# User Yuya Nishihara <<a href="mailto:yuya@tcha.org" target="_blank" rel="noreferrer">yuya@tcha.org</a>><br>
# Date 1561887163 -32400<br>
#      Sun Jun 30 18:32:43 2019 +0900<br>
# Node ID 72ab74c704053b2212b874a902574fedadad4252<br>
# Parent  904e0da2e195d2a29977ceccdd25480233c34d7a<br>
rust-dirstate: add helper to iterate ancestor paths<br>
<br>
This is modeled after std::path::Path::ancestors().<br>
<br>
find_dirs(b"") yields b"" because Mercurial's util.finddirs() works in that<br>
way, and the test case for DirsMultiset expects such behavior.<br></blockquote></div></div><div dir="auto"><br></div><div dir="auto">That's also how <span style="font-family:sans-serif">std::path::Path::ancestors() works, it seems.</span></div><div dir="auto"><span style="font-family:sans-serif"><br></span></div><div dir="auto"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
diff --git a/rust/hg-core/src/utils/<a href="http://files.rs" rel="noreferrer noreferrer" target="_blank">files.rs</a> b/rust/hg-core/src/utils/<a href="http://files.rs" rel="noreferrer noreferrer" target="_blank">files.rs</a><br>
--- a/rust/hg-core/src/utils/<a href="http://files.rs" rel="noreferrer noreferrer" target="_blank">files.rs</a><br>
+++ b/rust/hg-core/src/utils/<a href="http://files.rs" rel="noreferrer noreferrer" target="_blank">files.rs</a><br>
@@ -1,3 +1,4 @@<br>
+use std::iter::FusedIterator;<br>
 use std::path::Path;<br>
<br>
 pub fn get_path_from_bytes(bytes: &[u8]) -> &Path {<br>
@@ -17,3 +18,66 @@ pub fn get_path_from_bytes(bytes: &[u8])<br>
<br>
     Path::new(os_str)<br>
 }<br>
+<br>
+/// An iterator over repository path yielding itself and its ancestors.<br>
+#[derive(Copy, Clone, Debug)]<br>
+pub struct Ancestors<'a> {<br>
+    next: Option<&'a [u8]>,<br>
+}<br>
+<br>
+impl<'a> Iterator for Ancestors<'a> {<br>
+    // if we had an HgPath type, this would yield &'a HgPath<br>
+    type Item = &'a [u8];<br>
+<br>
+    fn next(&mut self) -> Option<Self::Item> {<br>
+        let next = self.next;<br>
+        self.next = match self.next {<br>
+            Some(s) if s.is_empty() => None,<br>
+            Some(s) => {<br>
+                let p = s.iter().rposition(|&c| c == b'/').unwrap_or(0);<br>
+                Some(&s[..p])<br>
+            }<br>
+            None => None,<br>
+        };<br>
+        next<br>
+    }<br>
+}<br>
+<br>
+impl<'a> FusedIterator for Ancestors<'a> {}<br>
+<br>
+/// Returns an iterator yielding ancestor directories of the given repository<br>
+/// path.<br>
+///<br>
+/// The path is separated by '/', and must not start with '/'.<br>
+///<br>
+/// The path itself isn't included unless it is b"" (meaning the root<br>
+/// directory.)<br>
+pub fn find_dirs<'a>(path: &'a [u8]) -> Ancestors<'a> {<br>
+    let mut dirs = Ancestors { next: Some(path) };<br>
+    if !path.is_empty() {<br>
+        dirs.next(); // skip itself<br>
+    }<br>
+    dirs<br>
+}<br>
+<br>
+#[cfg(test)]<br>
+mod tests {<br>
+    #[test]<br>
+    fn find_dirs_some() {<br>
+        let mut dirs = super::find_dirs(b"foo/bar/baz");<br>
+        assert_eq!(dirs.next(), Some(b"foo/bar".as_ref()));<br>
+        assert_eq!(dirs.next(), Some(b"foo".as_ref()));<br>
+        assert_eq!(dirs.next(), Some(b"".as_ref()));<br>
+        assert_eq!(dirs.next(), None);<br>
+        assert_eq!(dirs.next(), None);<br>
+    }<br>
+<br>
+    #[test]<br>
+    fn find_dirs_empty() {<br>
+        // looks weird, but mercurial.util.finddirs(b"") yields b""<br>
+        let mut dirs = super::find_dirs(b"");<br>
+        assert_eq!(dirs.next(), Some(b"".as_ref()));<br>
+        assert_eq!(dirs.next(), None);<br>
+        assert_eq!(dirs.next(), None);<br>
+    }<br>
+}<br>
_______________________________________________<br>
Mercurial-devel mailing list<br>
<a href="mailto:Mercurial-devel@mercurial-scm.org" target="_blank" rel="noreferrer">Mercurial-devel@mercurial-scm.org</a><br>
<a href="https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel" rel="noreferrer noreferrer" target="_blank">https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel</a><br>
</blockquote></div></div></div>