##// END OF EJS Templates
rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`...
rust-matchers: add `Matcher` trait and implement `AlwaysMatcher` In our quest of a faster Mercurial, we have arrived at the point where we need to implement the matchers in Rust. This RFC mainly for the `Matcher` trait to see if the changes proposed feel fine to people with more experience on the matter. While the `AlwaysMatcher` implementation is here as a trivial example, it should be the first step towards matchers use in Rust as it is currently the only supported one. Notable changes: - `exact` is renamed to `exact_match` - enums for `visit*` methods with `Recursive` instead of `'all'`, etc. - a new `roots`, separate from `file_set` - no `bad`, `explicitdir` or `traversedir` functions as they can be passed to the high functions instead of the matchers Thanks to Martin for suggesting the last two (most important) changes and for reaching out to help a few weeks ago. Differential Revision: https://phab.mercurial-scm.org/D7178

File last commit:

r43565:99394e6c default
r43742:a77d4fe3 default
Show More
files.rs
128 lines | 3.4 KiB | application/rls-services+xml | RustLexer
Raphaël Gomès
rust-docstrings: add missing module docstrings...
r42996 // 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.
Raphaël Gomès
rust-hgpath: replace all paths and filenames with HgPath/HgPathBuf...
r43227 use crate::utils::hg_path::{HgPath, HgPathBuf};
Yuya Nishihara
rust-dirstate: add helper to iterate ancestor paths...
r42789 use std::iter::FusedIterator;
Raphaël Gomès
rust-hgpath: replace all paths and filenames with HgPath/HgPathBuf...
r43227
Raphaël Gomès
rust-dirstate-status: add first Rust implementation of `dirstate.status`...
r43565 use std::fs::Metadata;
Raphaël Gomès
rust-filepatterns: use bytes instead of String...
r42630 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);
}
Raphaël Gomès
rust-cross-platform: remove `unimplemented!` to get compile-time errors...
r43544 // TODO Handle other platforms
// TODO: convert from WTF8 to Windows MBCS (ANSI encoding).
// Perhaps, the return type would have to be Result<PathBuf>.
Raphaël Gomès
rust-filepatterns: use bytes instead of String...
r42630
Path::new(os_str)
}
Yuya Nishihara
rust-dirstate: add helper to iterate ancestor paths...
r42789
/// An iterator over repository path yielding itself and its ancestors.
#[derive(Copy, Clone, Debug)]
pub struct Ancestors<'a> {
Raphaël Gomès
rust-hgpath: replace all paths and filenames with HgPath/HgPathBuf...
r43227 next: Option<&'a HgPath>,
Yuya Nishihara
rust-dirstate: add helper to iterate ancestor paths...
r42789 }
impl<'a> Iterator for Ancestors<'a> {
Raphaël Gomès
rust-hgpath: replace all paths and filenames with HgPath/HgPathBuf...
r43227 type Item = &'a HgPath;
Yuya Nishihara
rust-dirstate: add helper to iterate ancestor paths...
r42789
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) => {
Raphaël Gomès
rust-hgpath: replace all paths and filenames with HgPath/HgPathBuf...
r43227 let p = s.bytes().rposition(|c| *c == b'/').unwrap_or(0);
Some(HgPath::new(&s.as_bytes()[..p]))
Yuya Nishihara
rust-dirstate: add helper to iterate ancestor paths...
r42789 }
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.)
Raphaël Gomès
rust-hgpath: replace all paths and filenames with HgPath/HgPathBuf...
r43227 pub fn find_dirs<'a>(path: &'a HgPath) -> Ancestors<'a> {
Yuya Nishihara
rust-dirstate: add helper to iterate ancestor paths...
r42789 let mut dirs = Ancestors { next: Some(path) };
if !path.is_empty() {
dirs.next(); // skip itself
}
dirs
}
Raphaël Gomès
rust-hgpath: replace all paths and filenames with HgPath/HgPathBuf...
r43227 /// TODO more than ASCII?
pub fn normalize_case(path: &HgPath) -> HgPathBuf {
Raphaël Gomès
rust-utils: add normalize_case util to mirror Python one...
r43108 #[cfg(windows)] // NTFS compares via upper()
Raphaël Gomès
rust-hgpath: replace all paths and filenames with HgPath/HgPathBuf...
r43227 return path.to_ascii_uppercase();
Raphaël Gomès
rust-utils: add normalize_case util to mirror Python one...
r43108 #[cfg(unix)]
Raphaël Gomès
rust-hgpath: replace all paths and filenames with HgPath/HgPathBuf...
r43227 path.to_ascii_lowercase()
Raphaël Gomès
rust-utils: add normalize_case util to mirror Python one...
r43108 }
Raphaël Gomès
rust-dirstate-status: add first Rust implementation of `dirstate.status`...
r43565 #[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(),
}
}
}
Yuya Nishihara
rust-dirstate: add helper to iterate ancestor paths...
r42789 #[cfg(test)]
mod tests {
Raphaël Gomès
rust-hgpath: replace all paths and filenames with HgPath/HgPathBuf...
r43227 use super::*;
Yuya Nishihara
rust-dirstate: add helper to iterate ancestor paths...
r42789 #[test]
fn find_dirs_some() {
Raphaël Gomès
rust-hgpath: replace all paths and filenames with HgPath/HgPathBuf...
r43227 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"")));
Yuya Nishihara
rust-dirstate: add helper to iterate ancestor paths...
r42789 assert_eq!(dirs.next(), None);
assert_eq!(dirs.next(), None);
}
#[test]
fn find_dirs_empty() {
// looks weird, but mercurial.util.finddirs(b"") yields b""
Raphaël Gomès
rust-hgpath: replace all paths and filenames with HgPath/HgPathBuf...
r43227 let mut dirs = super::find_dirs(HgPath::new(b""));
assert_eq!(dirs.next(), Some(HgPath::new(b"")));
Yuya Nishihara
rust-dirstate: add helper to iterate ancestor paths...
r42789 assert_eq!(dirs.next(), None);
assert_eq!(dirs.next(), None);
}
}