Mercurial > hg
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 } |