Mercurial > hg
view rust/hg-core/src/utils/files.rs @ 43633:0b7733719d21
utils: move finddirs() to pathutil
This is a follow-up to c21aca51b392 (utils: move the `dirs` definition
in pathutil (API), 2019-11-06). finddirs() is closely related to dirs
and used by it.
Differential Revision: https://phab.mercurial-scm.org/D7388
author | Martin von Zweigbergk <martinvonz@google.com> |
---|---|
date | Thu, 14 Nov 2019 08:03:26 -0800 |
parents | 99394e6c5d12 |
children | ee3872c14ab3 |
line wrap: on
line source
// files.rs // // Copyright 2019 // Raphaël Gomès <rgomes@octobus.net>, // Yuya Nishihara <yuya@tcha.org> // // This software may be used and distributed according to the terms of the // GNU General Public License version 2 or any later version. //! Functions for fiddling with files. use crate::utils::hg_path::{HgPath, HgPathBuf}; use std::iter::FusedIterator; use std::fs::Metadata; use std::path::Path; pub fn get_path_from_bytes(bytes: &[u8]) -> &Path { let os_str; #[cfg(unix)] { use std::os::unix::ffi::OsStrExt; os_str = std::ffi::OsStr::from_bytes(bytes); } // TODO Handle other platforms // TODO: convert from WTF8 to Windows MBCS (ANSI encoding). // Perhaps, the return type would have to be Result<PathBuf>. 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 HgPath>, } impl<'a> Iterator for Ancestors<'a> { type Item = &'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) => { let p = s.bytes().rposition(|c| *c == b'/').unwrap_or(0); Some(HgPath::new(&s.as_bytes()[..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 HgPath) -> Ancestors<'a> { let mut dirs = Ancestors { next: Some(path) }; 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() return path.to_ascii_uppercase(); #[cfg(unix)] path.to_ascii_lowercase() } #[derive(Eq, PartialEq, Ord, PartialOrd, Copy, Clone)] pub struct HgMetadata { pub st_dev: u64, pub st_mode: u32, pub st_nlink: u64, pub st_size: u64, pub st_mtime: i64, pub st_ctime: i64, } // TODO support other plaforms #[cfg(unix)] impl HgMetadata { pub fn from_metadata(metadata: Metadata) -> Self { use std::os::unix::fs::MetadataExt; Self { st_dev: metadata.dev(), st_mode: metadata.mode(), st_nlink: metadata.nlink(), st_size: metadata.size(), st_mtime: metadata.mtime(), st_ctime: metadata.ctime(), } } } #[cfg(test)] mod tests { use super::*; #[test] fn find_dirs_some() { let mut dirs = super::find_dirs(HgPath::new(b"foo/bar/baz")); assert_eq!(dirs.next(), Some(HgPath::new(b"foo/bar"))); assert_eq!(dirs.next(), Some(HgPath::new(b"foo"))); assert_eq!(dirs.next(), Some(HgPath::new(b""))); assert_eq!(dirs.next(), None); assert_eq!(dirs.next(), None); } #[test] fn find_dirs_empty() { // looks weird, but mercurial.pathutil.finddirs(b"") yields b"" let mut dirs = super::find_dirs(HgPath::new(b"")); assert_eq!(dirs.next(), Some(HgPath::new(b""))); assert_eq!(dirs.next(), None); assert_eq!(dirs.next(), None); } }