comparison rust/hg-core/src/utils/files.rs @ 44267:0e9ac3968b56

rust-dirs-multiset: add `DirsChildrenMultiset` In a future patch, this structure will be needed to store information needed by the (also upcoming) `IgnoreMatcher`. Differential Revision: https://phab.mercurial-scm.org/D7869
author Raphaël Gomès <rgomes@octobus.net>
date Tue, 14 Jan 2020 17:04:32 +0100
parents c18dd48cea4a
children 4caac36c66bc
comparison
equal deleted inserted replaced
44266:9ab4830e9e3d 44267:0e9ac3968b56
8 // GNU General Public License version 2 or any later version. 8 // GNU General Public License version 2 or any later version.
9 9
10 //! Functions for fiddling with files. 10 //! Functions for fiddling with files.
11 11
12 use crate::utils::hg_path::{HgPath, HgPathBuf}; 12 use crate::utils::hg_path::{HgPath, HgPathBuf};
13 use std::iter::FusedIterator;
14 13
15 use crate::utils::replace_slice; 14 use crate::utils::replace_slice;
16 use lazy_static::lazy_static; 15 use lazy_static::lazy_static;
17 use std::fs::Metadata; 16 use std::fs::Metadata;
17 use std::iter::FusedIterator;
18 use std::path::Path; 18 use std::path::Path;
19 19
20 pub fn get_path_from_bytes(bytes: &[u8]) -> &Path { 20 pub fn get_path_from_bytes(bytes: &[u8]) -> &Path {
21 let os_str; 21 let os_str;
22 #[cfg(unix)] 22 #[cfg(unix)]
62 } 62 }
63 } 63 }
64 64
65 impl<'a> FusedIterator for Ancestors<'a> {} 65 impl<'a> FusedIterator for Ancestors<'a> {}
66 66
67 /// An iterator over repository path yielding itself and its ancestors.
68 #[derive(Copy, Clone, Debug)]
69 pub(crate) struct AncestorsWithBase<'a> {
70 next: Option<(&'a HgPath, &'a HgPath)>,
71 }
72
73 impl<'a> Iterator for AncestorsWithBase<'a> {
74 type Item = (&'a HgPath, &'a HgPath);
75
76 fn next(&mut self) -> Option<Self::Item> {
77 let next = self.next;
78 self.next = match self.next {
79 Some((s, _)) if s.is_empty() => None,
80 Some((s, _)) => Some(s.split_filename()),
81 None => None,
82 };
83 next
84 }
85 }
86
87 impl<'a> FusedIterator for AncestorsWithBase<'a> {}
88
67 /// Returns an iterator yielding ancestor directories of the given repository 89 /// Returns an iterator yielding ancestor directories of the given repository
68 /// path. 90 /// path.
69 /// 91 ///
70 /// The path is separated by '/', and must not start with '/'. 92 /// The path is separated by '/', and must not start with '/'.
71 /// 93 ///
72 /// The path itself isn't included unless it is b"" (meaning the root 94 /// The path itself isn't included unless it is b"" (meaning the root
73 /// directory.) 95 /// directory.)
74 pub fn find_dirs<'a>(path: &'a HgPath) -> Ancestors<'a> { 96 pub fn find_dirs<'a>(path: &'a HgPath) -> Ancestors<'a> {
75 let mut dirs = Ancestors { next: Some(path) }; 97 let mut dirs = Ancestors { next: Some(path) };
98 if !path.is_empty() {
99 dirs.next(); // skip itself
100 }
101 dirs
102 }
103
104 /// Returns an iterator yielding ancestor directories of the given repository
105 /// path.
106 ///
107 /// The path is separated by '/', and must not start with '/'.
108 ///
109 /// The path itself isn't included unless it is b"" (meaning the root
110 /// directory.)
111 pub(crate) fn find_dirs_with_base<'a>(
112 path: &'a HgPath,
113 ) -> AncestorsWithBase<'a> {
114 let mut dirs = AncestorsWithBase {
115 next: Some((path, HgPath::new(b""))),
116 };
76 if !path.is_empty() { 117 if !path.is_empty() {
77 dirs.next(); // skip itself 118 dirs.next(); // skip itself
78 } 119 }
79 dirs 120 dirs
80 } 121 }
168 let mut dirs = super::find_dirs(HgPath::new(b"")); 209 let mut dirs = super::find_dirs(HgPath::new(b""));
169 assert_eq!(dirs.next(), Some(HgPath::new(b""))); 210 assert_eq!(dirs.next(), Some(HgPath::new(b"")));
170 assert_eq!(dirs.next(), None); 211 assert_eq!(dirs.next(), None);
171 assert_eq!(dirs.next(), None); 212 assert_eq!(dirs.next(), None);
172 } 213 }
173 } 214
215 #[test]
216 fn test_find_dirs_with_base_some() {
217 let mut dirs = super::find_dirs_with_base(HgPath::new(b"foo/bar/baz"));
218 assert_eq!(
219 dirs.next(),
220 Some((HgPath::new(b"foo/bar"), HgPath::new(b"baz")))
221 );
222 assert_eq!(
223 dirs.next(),
224 Some((HgPath::new(b"foo"), HgPath::new(b"bar")))
225 );
226 assert_eq!(dirs.next(), Some((HgPath::new(b""), HgPath::new(b"foo"))));
227 assert_eq!(dirs.next(), None);
228 assert_eq!(dirs.next(), None);
229 }
230
231 #[test]
232 fn test_find_dirs_with_base_empty() {
233 let mut dirs = super::find_dirs_with_base(HgPath::new(b""));
234 assert_eq!(dirs.next(), Some((HgPath::new(b""), HgPath::new(b""))));
235 assert_eq!(dirs.next(), None);
236 assert_eq!(dirs.next(), None);
237 }
238 }