Mercurial > hg
view rust/hg-core/src/matchers.rs @ 43863:bc7d8f45c3b6
rust-dirs: handle forgotten `Result`s
In 1fe2e574616e I introduced a temporary bugfix to align Rust code with a new
behavior from C/Python and forgot about a few `Result`s (cargo's compiler cache
does not re-emit warnings on cached modules). This fixes it.
For the record, I am still unsure that this behavior change is a good idea.
Note: I was already quite unhappy with the setters and getters for the
`DirstateMap` and, indirectly, `Dirs`, and this only further reinforces my
feelings. I hope we can one day fix that situation at the type level; Georges
Racinet and I were just talking about devising a POC for using the builder
pattern in the context of FFI with Python, we'll see what comes out of it.
Differential Revision: https://phab.mercurial-scm.org/D7609
author | Raphaël Gomès <rgomes@octobus.net> |
---|---|
date | Thu, 12 Dec 2019 15:55:25 +0100 |
parents | 542c8b277261 |
children | 69c4f3cf2cdf |
line wrap: on
line source
// matchers.rs // // Copyright 2019 Raphaël Gomès <rgomes@octobus.net> // // This software may be used and distributed according to the terms of the // GNU General Public License version 2 or any later version. //! Structs and types for matching files and directories. use crate::utils::hg_path::HgPath; use std::collections::HashSet; pub enum VisitChildrenSet<'a> { /// Don't visit anything Empty, /// Only visit this directory This, /// Visit this directory and these subdirectories /// TODO Should we implement a `NonEmptyHashSet`? Set(HashSet<&'a HgPath>), /// Visit this directory and all subdirectories Recursive, } pub trait Matcher { /// Explicitly listed files fn file_set(&self) -> Option<&HashSet<&HgPath>>; /// Returns whether `filename` is in `file_set` fn exact_match(&self, filename: impl AsRef<HgPath>) -> bool; /// Returns whether `filename` is matched by this matcher fn matches(&self, filename: impl AsRef<HgPath>) -> bool; /// Decides whether a directory should be visited based on whether it /// has potential matches in it or one of its subdirectories, and /// potentially lists which subdirectories of that directory should be /// visited. This is based on the match's primary, included, and excluded /// patterns. /// /// # Example /// /// Assume matchers `['path:foo/bar', 'rootfilesin:qux']`, we would /// return the following values (assuming the implementation of /// visit_children_set is capable of recognizing this; some implementations /// are not). /// /// ```ignore /// '' -> {'foo', 'qux'} /// 'baz' -> set() /// 'foo' -> {'bar'} /// // Ideally this would be `Recursive`, but since the prefix nature of /// // matchers is applied to the entire matcher, we have to downgrade this /// // to `This` due to the (yet to be implemented in Rust) non-prefix /// // `RootFilesIn'-kind matcher being mixed in. /// 'foo/bar' -> 'this' /// 'qux' -> 'this' /// ``` /// # Important /// /// Most matchers do not know if they're representing files or /// directories. They see `['path:dir/f']` and don't know whether `f` is a /// file or a directory, so `visit_children_set('dir')` for most matchers /// will return `HashSet{ HgPath { "f" } }`, but if the matcher knows it's /// a file (like the yet to be implemented in Rust `ExactMatcher` does), /// it may return `VisitChildrenSet::This`. /// Do not rely on the return being a `HashSet` indicating that there are /// no files in this dir to investigate (or equivalently that if there are /// files to investigate in 'dir' that it will always return /// `VisitChildrenSet::This`). fn visit_children_set( &self, directory: impl AsRef<HgPath>, ) -> VisitChildrenSet; /// Matcher will match everything and `files_set()` will be empty: /// optimization might be possible. fn matches_everything(&self) -> bool; /// Matcher will match exactly the files in `files_set()`: optimization /// might be possible. fn is_exact(&self) -> bool; } /// Matches everything. ///``` /// use hg::{ matchers::{Matcher, AlwaysMatcher}, utils::hg_path::HgPath }; /// /// let matcher = AlwaysMatcher; /// /// assert_eq!(true, matcher.matches(HgPath::new(b"whatever"))); /// assert_eq!(true, matcher.matches(HgPath::new(b"b.txt"))); /// assert_eq!(true, matcher.matches(HgPath::new(b"main.c"))); /// assert_eq!(true, matcher.matches(HgPath::new(br"re:.*\.c$"))); /// ``` #[derive(Debug)] pub struct AlwaysMatcher; impl Matcher for AlwaysMatcher { fn file_set(&self) -> Option<&HashSet<&HgPath>> { None } fn exact_match(&self, _filename: impl AsRef<HgPath>) -> bool { false } fn matches(&self, _filename: impl AsRef<HgPath>) -> bool { true } fn visit_children_set( &self, _directory: impl AsRef<HgPath>, ) -> VisitChildrenSet { VisitChildrenSet::Recursive } fn matches_everything(&self) -> bool { true } fn is_exact(&self) -> bool { false } }