Mercurial > hg
diff 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 |
line wrap: on
line diff
--- a/rust/hg-core/src/utils/files.rs Tue Jan 14 16:50:35 2020 +0100 +++ b/rust/hg-core/src/utils/files.rs Tue Jan 14 17:04:32 2020 +0100 @@ -10,11 +10,11 @@ //! Functions for fiddling with files. use crate::utils::hg_path::{HgPath, HgPathBuf}; -use std::iter::FusedIterator; use crate::utils::replace_slice; use lazy_static::lazy_static; use std::fs::Metadata; +use std::iter::FusedIterator; use std::path::Path; pub fn get_path_from_bytes(bytes: &[u8]) -> &Path { @@ -64,6 +64,28 @@ impl<'a> FusedIterator for Ancestors<'a> {} +/// An iterator over repository path yielding itself and its ancestors. +#[derive(Copy, Clone, Debug)] +pub(crate) struct AncestorsWithBase<'a> { + next: Option<(&'a HgPath, &'a HgPath)>, +} + +impl<'a> Iterator for AncestorsWithBase<'a> { + type Item = (&'a HgPath, &'a HgPath); + + 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, _)) => Some(s.split_filename()), + None => None, + }; + next + } +} + +impl<'a> FusedIterator for AncestorsWithBase<'a> {} + /// Returns an iterator yielding ancestor directories of the given repository /// path. /// @@ -79,6 +101,25 @@ dirs } +/// 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(crate) fn find_dirs_with_base<'a>( + path: &'a HgPath, +) -> AncestorsWithBase<'a> { + let mut dirs = AncestorsWithBase { + next: Some((path, HgPath::new(b""))), + }; + if !path.is_empty() { + dirs.next(); // skip itself + } + dirs +} + /// TODO more than ASCII? pub fn normalize_case(path: &HgPath) -> HgPathBuf { #[cfg(windows)] // NTFS compares via upper() @@ -170,4 +211,28 @@ assert_eq!(dirs.next(), None); assert_eq!(dirs.next(), None); } + + #[test] + fn test_find_dirs_with_base_some() { + let mut dirs = super::find_dirs_with_base(HgPath::new(b"foo/bar/baz")); + assert_eq!( + dirs.next(), + Some((HgPath::new(b"foo/bar"), HgPath::new(b"baz"))) + ); + assert_eq!( + dirs.next(), + Some((HgPath::new(b"foo"), HgPath::new(b"bar"))) + ); + assert_eq!(dirs.next(), Some((HgPath::new(b""), HgPath::new(b"foo")))); + assert_eq!(dirs.next(), None); + assert_eq!(dirs.next(), None); + } + + #[test] + fn test_find_dirs_with_base_empty() { + let mut dirs = super::find_dirs_with_base(HgPath::new(b"")); + assert_eq!(dirs.next(), Some((HgPath::new(b""), HgPath::new(b"")))); + assert_eq!(dirs.next(), None); + assert_eq!(dirs.next(), None); + } }