comparison rust/hg-core/src/matchers.rs @ 43914:69c4f3cf2cdf

rust-matchers: add `FileMatcher` implementation Mercurial defines an `exactmatcher`, I find `FileMatcher` to be clearer, but am not opposed to using the old name. This change also switched the order of `assert_eq` arguments as it is clearer that way for most people. Differential Revision: https://phab.mercurial-scm.org/D7528
author Raphaël Gomès <rgomes@octobus.net>
date Fri, 29 Nov 2019 18:54:06 +0100
parents bc7d8f45c3b6
children 72bced4f2936
comparison
equal deleted inserted replaced
43913:4b7d5d10c45d 43914:69c4f3cf2cdf
5 // This software may be used and distributed according to the terms of the 5 // This software may be used and distributed according to the terms of the
6 // GNU General Public License version 2 or any later version. 6 // GNU General Public License version 2 or any later version.
7 7
8 //! Structs and types for matching files and directories. 8 //! Structs and types for matching files and directories.
9 9
10 use crate::utils::hg_path::HgPath; 10 use crate::{utils::hg_path::HgPath, DirsMultiset, DirstateMapError};
11 use std::collections::HashSet; 11 use std::collections::HashSet;
12 use std::iter::FromIterator;
12 13
13 pub enum VisitChildrenSet<'a> { 14 pub enum VisitChildrenSet<'a> {
14 /// Don't visit anything 15 /// Don't visit anything
15 Empty, 16 Empty,
16 /// Only visit this directory 17 /// Only visit this directory
81 ///``` 82 ///```
82 /// use hg::{ matchers::{Matcher, AlwaysMatcher}, utils::hg_path::HgPath }; 83 /// use hg::{ matchers::{Matcher, AlwaysMatcher}, utils::hg_path::HgPath };
83 /// 84 ///
84 /// let matcher = AlwaysMatcher; 85 /// let matcher = AlwaysMatcher;
85 /// 86 ///
86 /// assert_eq!(true, matcher.matches(HgPath::new(b"whatever"))); 87 /// assert_eq!(matcher.matches(HgPath::new(b"whatever")), true);
87 /// assert_eq!(true, matcher.matches(HgPath::new(b"b.txt"))); 88 /// assert_eq!(matcher.matches(HgPath::new(b"b.txt")), true);
88 /// assert_eq!(true, matcher.matches(HgPath::new(b"main.c"))); 89 /// assert_eq!(matcher.matches(HgPath::new(b"main.c")), true);
89 /// assert_eq!(true, matcher.matches(HgPath::new(br"re:.*\.c$"))); 90 /// assert_eq!(matcher.matches(HgPath::new(br"re:.*\.c$")), true);
90 /// ``` 91 /// ```
91 #[derive(Debug)] 92 #[derive(Debug)]
92 pub struct AlwaysMatcher; 93 pub struct AlwaysMatcher;
93 94
94 impl Matcher for AlwaysMatcher { 95 impl Matcher for AlwaysMatcher {
112 } 113 }
113 fn is_exact(&self) -> bool { 114 fn is_exact(&self) -> bool {
114 false 115 false
115 } 116 }
116 } 117 }
118
119 /// Matches the input files exactly. They are interpreted as paths, not
120 /// patterns.
121 ///
122 ///```
123 /// use hg::{ matchers::{Matcher, FileMatcher}, utils::hg_path::HgPath };
124 ///
125 /// let files = [HgPath::new(b"a.txt"), HgPath::new(br"re:.*\.c$")];
126 /// let matcher = FileMatcher::new(&files).unwrap();
127 ///
128 /// assert_eq!(matcher.matches(HgPath::new(b"a.txt")), true);
129 /// assert_eq!(matcher.matches(HgPath::new(b"b.txt")), false);
130 /// assert_eq!(matcher.matches(HgPath::new(b"main.c")), false);
131 /// assert_eq!(matcher.matches(HgPath::new(br"re:.*\.c$")), true);
132 /// ```
133 #[derive(Debug)]
134 pub struct FileMatcher<'a> {
135 files: HashSet<&'a HgPath>,
136 dirs: DirsMultiset,
137 }
138
139 impl<'a> FileMatcher<'a> {
140 pub fn new(
141 files: &'a [impl AsRef<HgPath>],
142 ) -> Result<Self, DirstateMapError> {
143 Ok(Self {
144 files: HashSet::from_iter(files.iter().map(|f| f.as_ref())),
145 dirs: DirsMultiset::from_manifest(files)?,
146 })
147 }
148 fn inner_matches(&self, filename: impl AsRef<HgPath>) -> bool {
149 self.files.contains(filename.as_ref())
150 }
151 }
152
153 impl<'a> Matcher for FileMatcher<'a> {
154 fn file_set(&self) -> Option<&HashSet<&HgPath>> {
155 Some(&self.files)
156 }
157 fn exact_match(&self, filename: impl AsRef<HgPath>) -> bool {
158 self.inner_matches(filename)
159 }
160 fn matches(&self, filename: impl AsRef<HgPath>) -> bool {
161 self.inner_matches(filename)
162 }
163 fn visit_children_set(
164 &self,
165 _directory: impl AsRef<HgPath>,
166 ) -> VisitChildrenSet {
167 // TODO implement once we have `status.traverse`
168 // This is useless until unknown files are taken into account
169 // Which will not need to happen before the `IncludeMatcher`.
170 unimplemented!()
171 }
172 fn matches_everything(&self) -> bool {
173 false
174 }
175 fn is_exact(&self) -> bool {
176 true
177 }
178 }