Mercurial > public > mercurial-scm > hg
comparison rust/hg-core/src/utils/files.rs @ 42586:cad3dde7a573
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.
author | Yuya Nishihara <yuya@tcha.org> |
---|---|
date | Sun, 30 Jun 2019 18:32:43 +0900 |
parents | f305f1d7d559 |
children | 4b3b27d567d5 |
comparison
equal
deleted
inserted
replaced
42585:ebf353aa4385 | 42586:cad3dde7a573 |
---|---|
1 use std::iter::FusedIterator; | |
1 use std::path::Path; | 2 use std::path::Path; |
2 | 3 |
3 pub fn get_path_from_bytes(bytes: &[u8]) -> &Path { | 4 pub fn get_path_from_bytes(bytes: &[u8]) -> &Path { |
4 let os_str; | 5 let os_str; |
5 #[cfg(unix)] | 6 #[cfg(unix)] |
15 os_str = std::ffi::OsString::from_wide(bytes); | 16 os_str = std::ffi::OsString::from_wide(bytes); |
16 } | 17 } |
17 | 18 |
18 Path::new(os_str) | 19 Path::new(os_str) |
19 } | 20 } |
21 | |
22 /// An iterator over repository path yielding itself and its ancestors. | |
23 #[derive(Copy, Clone, Debug)] | |
24 pub struct Ancestors<'a> { | |
25 next: Option<&'a [u8]>, | |
26 } | |
27 | |
28 impl<'a> Iterator for Ancestors<'a> { | |
29 // if we had an HgPath type, this would yield &'a HgPath | |
30 type Item = &'a [u8]; | |
31 | |
32 fn next(&mut self) -> Option<Self::Item> { | |
33 let next = self.next; | |
34 self.next = match self.next { | |
35 Some(s) if s.is_empty() => None, | |
36 Some(s) => { | |
37 let p = s.iter().rposition(|&c| c == b'/').unwrap_or(0); | |
38 Some(&s[..p]) | |
39 } | |
40 None => None, | |
41 }; | |
42 next | |
43 } | |
44 } | |
45 | |
46 impl<'a> FusedIterator for Ancestors<'a> {} | |
47 | |
48 /// Returns an iterator yielding ancestor directories of the given repository | |
49 /// path. | |
50 /// | |
51 /// The path is separated by '/', and must not start with '/'. | |
52 /// | |
53 /// The path itself isn't included unless it is b"" (meaning the root | |
54 /// directory.) | |
55 pub fn find_dirs<'a>(path: &'a [u8]) -> Ancestors<'a> { | |
56 let mut dirs = Ancestors { next: Some(path) }; | |
57 if !path.is_empty() { | |
58 dirs.next(); // skip itself | |
59 } | |
60 dirs | |
61 } | |
62 | |
63 #[cfg(test)] | |
64 mod tests { | |
65 #[test] | |
66 fn find_dirs_some() { | |
67 let mut dirs = super::find_dirs(b"foo/bar/baz"); | |
68 assert_eq!(dirs.next(), Some(b"foo/bar".as_ref())); | |
69 assert_eq!(dirs.next(), Some(b"foo".as_ref())); | |
70 assert_eq!(dirs.next(), Some(b"".as_ref())); | |
71 assert_eq!(dirs.next(), None); | |
72 assert_eq!(dirs.next(), None); | |
73 } | |
74 | |
75 #[test] | |
76 fn find_dirs_empty() { | |
77 // looks weird, but mercurial.util.finddirs(b"") yields b"" | |
78 let mut dirs = super::find_dirs(b""); | |
79 assert_eq!(dirs.next(), Some(b"".as_ref())); | |
80 assert_eq!(dirs.next(), None); | |
81 assert_eq!(dirs.next(), None); | |
82 } | |
83 } |