##// END OF EJS Templates
rust: use owned types in `Matcher`...
Raphaël Gomès -
r50241:137d6bb7 default
parent child Browse files
Show More
@@ -34,21 +34,21 b' use std::path::{Path, PathBuf};'
34 use micro_timer::timed;
34 use micro_timer::timed;
35
35
36 #[derive(Debug, PartialEq)]
36 #[derive(Debug, PartialEq)]
37 pub enum VisitChildrenSet<'a> {
37 pub enum VisitChildrenSet {
38 /// Don't visit anything
38 /// Don't visit anything
39 Empty,
39 Empty,
40 /// Only visit this directory
40 /// Only visit this directory
41 This,
41 This,
42 /// Visit this directory and these subdirectories
42 /// Visit this directory and these subdirectories
43 /// TODO Should we implement a `NonEmptyHashSet`?
43 /// TODO Should we implement a `NonEmptyHashSet`?
44 Set(HashSet<&'a HgPath>),
44 Set(HashSet<HgPathBuf>),
45 /// Visit this directory and all subdirectories
45 /// Visit this directory and all subdirectories
46 Recursive,
46 Recursive,
47 }
47 }
48
48
49 pub trait Matcher {
49 pub trait Matcher {
50 /// Explicitly listed files
50 /// Explicitly listed files
51 fn file_set(&self) -> Option<&HashSet<&HgPath>>;
51 fn file_set(&self) -> Option<&HashSet<HgPathBuf>>;
52 /// Returns whether `filename` is in `file_set`
52 /// Returns whether `filename` is in `file_set`
53 fn exact_match(&self, filename: &HgPath) -> bool;
53 fn exact_match(&self, filename: &HgPath) -> bool;
54 /// Returns whether `filename` is matched by this matcher
54 /// Returns whether `filename` is matched by this matcher
@@ -114,7 +114,7 b' pub trait Matcher {'
114 pub struct AlwaysMatcher;
114 pub struct AlwaysMatcher;
115
115
116 impl Matcher for AlwaysMatcher {
116 impl Matcher for AlwaysMatcher {
117 fn file_set(&self) -> Option<&HashSet<&HgPath>> {
117 fn file_set(&self) -> Option<&HashSet<HgPathBuf>> {
118 None
118 None
119 }
119 }
120 fn exact_match(&self, _filename: &HgPath) -> bool {
120 fn exact_match(&self, _filename: &HgPath) -> bool {
@@ -140,8 +140,8 b' impl Matcher for AlwaysMatcher {'
140 ///```
140 ///```
141 /// use hg::{ matchers::{Matcher, FileMatcher}, utils::hg_path::{HgPath, HgPathBuf} };
141 /// use hg::{ matchers::{Matcher, FileMatcher}, utils::hg_path::{HgPath, HgPathBuf} };
142 ///
142 ///
143 /// let files = [HgPathBuf::from_bytes(b"a.txt"), HgPathBuf::from_bytes(br"re:.*\.c$")];
143 /// let files = vec![HgPathBuf::from_bytes(b"a.txt"), HgPathBuf::from_bytes(br"re:.*\.c$")];
144 /// let matcher = FileMatcher::new(&files).unwrap();
144 /// let matcher = FileMatcher::new(files).unwrap();
145 ///
145 ///
146 /// assert_eq!(matcher.matches(HgPath::new(b"a.txt")), true);
146 /// assert_eq!(matcher.matches(HgPath::new(b"a.txt")), true);
147 /// assert_eq!(matcher.matches(HgPath::new(b"b.txt")), false);
147 /// assert_eq!(matcher.matches(HgPath::new(b"b.txt")), false);
@@ -149,16 +149,17 b' impl Matcher for AlwaysMatcher {'
149 /// assert_eq!(matcher.matches(HgPath::new(br"re:.*\.c$")), true);
149 /// assert_eq!(matcher.matches(HgPath::new(br"re:.*\.c$")), true);
150 /// ```
150 /// ```
151 #[derive(Debug)]
151 #[derive(Debug)]
152 pub struct FileMatcher<'a> {
152 pub struct FileMatcher {
153 files: HashSet<&'a HgPath>,
153 files: HashSet<HgPathBuf>,
154 dirs: DirsMultiset,
154 dirs: DirsMultiset,
155 }
155 }
156
156
157 impl<'a> FileMatcher<'a> {
157 impl FileMatcher {
158 pub fn new(files: &'a [HgPathBuf]) -> Result<Self, DirstateMapError> {
158 pub fn new(files: Vec<HgPathBuf>) -> Result<Self, DirstateMapError> {
159 let dirs = DirsMultiset::from_manifest(&files)?;
159 Ok(Self {
160 Ok(Self {
160 files: HashSet::from_iter(files.iter().map(AsRef::as_ref)),
161 files: HashSet::from_iter(files.into_iter()),
161 dirs: DirsMultiset::from_manifest(files)?,
162 dirs,
162 })
163 })
163 }
164 }
164 fn inner_matches(&self, filename: &HgPath) -> bool {
165 fn inner_matches(&self, filename: &HgPath) -> bool {
@@ -166,8 +167,8 b" impl<'a> FileMatcher<'a> {"
166 }
167 }
167 }
168 }
168
169
169 impl<'a> Matcher for FileMatcher<'a> {
170 impl Matcher for FileMatcher {
170 fn file_set(&self) -> Option<&HashSet<&HgPath>> {
171 fn file_set(&self) -> Option<&HashSet<HgPathBuf>> {
171 Some(&self.files)
172 Some(&self.files)
172 }
173 }
173 fn exact_match(&self, filename: &HgPath) -> bool {
174 fn exact_match(&self, filename: &HgPath) -> bool {
@@ -180,10 +181,10 b" impl<'a> Matcher for FileMatcher<'a> {"
180 if self.files.is_empty() || !self.dirs.contains(&directory) {
181 if self.files.is_empty() || !self.dirs.contains(&directory) {
181 return VisitChildrenSet::Empty;
182 return VisitChildrenSet::Empty;
182 }
183 }
183 let dirs_as_set = self.dirs.iter().map(Deref::deref).collect();
184 let mut candidates: HashSet<HgPathBuf> =
185 self.dirs.iter().cloned().collect();
184
186
185 let mut candidates: HashSet<&HgPath> =
187 candidates.extend(self.files.iter().cloned());
186 self.files.union(&dirs_as_set).cloned().collect();
187 candidates.remove(HgPath::new(b""));
188 candidates.remove(HgPath::new(b""));
188
189
189 if !directory.as_ref().is_empty() {
190 if !directory.as_ref().is_empty() {
@@ -192,7 +193,9 b" impl<'a> Matcher for FileMatcher<'a> {"
192 .iter()
193 .iter()
193 .filter_map(|c| {
194 .filter_map(|c| {
194 if c.as_bytes().starts_with(&directory) {
195 if c.as_bytes().starts_with(&directory) {
195 Some(HgPath::new(&c.as_bytes()[directory.len()..]))
196 Some(HgPathBuf::from_bytes(
197 &c.as_bytes()[directory.len()..],
198 ))
196 } else {
199 } else {
197 None
200 None
198 }
201 }
@@ -207,10 +210,10 b" impl<'a> Matcher for FileMatcher<'a> {"
207 // subdir will be in there without a slash.
210 // subdir will be in there without a slash.
208 VisitChildrenSet::Set(
211 VisitChildrenSet::Set(
209 candidates
212 candidates
210 .iter()
213 .into_iter()
211 .filter_map(|c| {
214 .filter_map(|c| {
212 if c.bytes().all(|b| *b != b'/') {
215 if c.bytes().all(|b| *b != b'/') {
213 Some(*c)
216 Some(c)
214 } else {
217 } else {
215 None
218 None
216 }
219 }
@@ -256,7 +259,7 b" pub struct IncludeMatcher<'a> {"
256 }
259 }
257
260
258 impl<'a> Matcher for IncludeMatcher<'a> {
261 impl<'a> Matcher for IncludeMatcher<'a> {
259 fn file_set(&self) -> Option<&HashSet<&HgPath>> {
262 fn file_set(&self) -> Option<&HashSet<HgPathBuf>> {
260 None
263 None
261 }
264 }
262
265
@@ -284,7 +287,9 b" impl<'a> Matcher for IncludeMatcher<'a> "
284 if self.parents.contains(directory.as_ref()) {
287 if self.parents.contains(directory.as_ref()) {
285 let multiset = self.get_all_parents_children();
288 let multiset = self.get_all_parents_children();
286 if let Some(children) = multiset.get(dir) {
289 if let Some(children) = multiset.get(dir) {
287 return VisitChildrenSet::Set(children.to_owned());
290 return VisitChildrenSet::Set(
291 children.into_iter().map(HgPathBuf::from).collect(),
292 );
288 }
293 }
289 }
294 }
290 VisitChildrenSet::Empty
295 VisitChildrenSet::Empty
@@ -721,24 +726,24 b' mod tests {'
721 fn test_filematcher_visit_children_set() {
726 fn test_filematcher_visit_children_set() {
722 // Visitchildrenset
727 // Visitchildrenset
723 let files = vec![HgPathBuf::from_bytes(b"dir/subdir/foo.txt")];
728 let files = vec![HgPathBuf::from_bytes(b"dir/subdir/foo.txt")];
724 let matcher = FileMatcher::new(&files).unwrap();
729 let matcher = FileMatcher::new(files).unwrap();
725
730
726 let mut set = HashSet::new();
731 let mut set = HashSet::new();
727 set.insert(HgPath::new(b"dir"));
732 set.insert(HgPathBuf::from_bytes(b"dir"));
728 assert_eq!(
733 assert_eq!(
729 matcher.visit_children_set(HgPath::new(b"")),
734 matcher.visit_children_set(HgPath::new(b"")),
730 VisitChildrenSet::Set(set)
735 VisitChildrenSet::Set(set)
731 );
736 );
732
737
733 let mut set = HashSet::new();
738 let mut set = HashSet::new();
734 set.insert(HgPath::new(b"subdir"));
739 set.insert(HgPathBuf::from_bytes(b"subdir"));
735 assert_eq!(
740 assert_eq!(
736 matcher.visit_children_set(HgPath::new(b"dir")),
741 matcher.visit_children_set(HgPath::new(b"dir")),
737 VisitChildrenSet::Set(set)
742 VisitChildrenSet::Set(set)
738 );
743 );
739
744
740 let mut set = HashSet::new();
745 let mut set = HashSet::new();
741 set.insert(HgPath::new(b"foo.txt"));
746 set.insert(HgPathBuf::from_bytes(b"foo.txt"));
742 assert_eq!(
747 assert_eq!(
743 matcher.visit_children_set(HgPath::new(b"dir/subdir")),
748 matcher.visit_children_set(HgPath::new(b"dir/subdir")),
744 VisitChildrenSet::Set(set)
749 VisitChildrenSet::Set(set)
@@ -767,40 +772,40 b' mod tests {'
767 // No file in a/b/c
772 // No file in a/b/c
768 HgPathBuf::from_bytes(b"a/b/c/d/file4.txt"),
773 HgPathBuf::from_bytes(b"a/b/c/d/file4.txt"),
769 ];
774 ];
770 let matcher = FileMatcher::new(&files).unwrap();
775 let matcher = FileMatcher::new(files).unwrap();
771
776
772 let mut set = HashSet::new();
777 let mut set = HashSet::new();
773 set.insert(HgPath::new(b"a"));
778 set.insert(HgPathBuf::from_bytes(b"a"));
774 set.insert(HgPath::new(b"rootfile.txt"));
779 set.insert(HgPathBuf::from_bytes(b"rootfile.txt"));
775 assert_eq!(
780 assert_eq!(
776 matcher.visit_children_set(HgPath::new(b"")),
781 matcher.visit_children_set(HgPath::new(b"")),
777 VisitChildrenSet::Set(set)
782 VisitChildrenSet::Set(set)
778 );
783 );
779
784
780 let mut set = HashSet::new();
785 let mut set = HashSet::new();
781 set.insert(HgPath::new(b"b"));
786 set.insert(HgPathBuf::from_bytes(b"b"));
782 set.insert(HgPath::new(b"file1.txt"));
787 set.insert(HgPathBuf::from_bytes(b"file1.txt"));
783 assert_eq!(
788 assert_eq!(
784 matcher.visit_children_set(HgPath::new(b"a")),
789 matcher.visit_children_set(HgPath::new(b"a")),
785 VisitChildrenSet::Set(set)
790 VisitChildrenSet::Set(set)
786 );
791 );
787
792
788 let mut set = HashSet::new();
793 let mut set = HashSet::new();
789 set.insert(HgPath::new(b"c"));
794 set.insert(HgPathBuf::from_bytes(b"c"));
790 set.insert(HgPath::new(b"file2.txt"));
795 set.insert(HgPathBuf::from_bytes(b"file2.txt"));
791 assert_eq!(
796 assert_eq!(
792 matcher.visit_children_set(HgPath::new(b"a/b")),
797 matcher.visit_children_set(HgPath::new(b"a/b")),
793 VisitChildrenSet::Set(set)
798 VisitChildrenSet::Set(set)
794 );
799 );
795
800
796 let mut set = HashSet::new();
801 let mut set = HashSet::new();
797 set.insert(HgPath::new(b"d"));
802 set.insert(HgPathBuf::from_bytes(b"d"));
798 assert_eq!(
803 assert_eq!(
799 matcher.visit_children_set(HgPath::new(b"a/b/c")),
804 matcher.visit_children_set(HgPath::new(b"a/b/c")),
800 VisitChildrenSet::Set(set)
805 VisitChildrenSet::Set(set)
801 );
806 );
802 let mut set = HashSet::new();
807 let mut set = HashSet::new();
803 set.insert(HgPath::new(b"file4.txt"));
808 set.insert(HgPathBuf::from_bytes(b"file4.txt"));
804 assert_eq!(
809 assert_eq!(
805 matcher.visit_children_set(HgPath::new(b"a/b/c/d")),
810 matcher.visit_children_set(HgPath::new(b"a/b/c/d")),
806 VisitChildrenSet::Set(set)
811 VisitChildrenSet::Set(set)
@@ -827,14 +832,14 b' mod tests {'
827 .unwrap();
832 .unwrap();
828
833
829 let mut set = HashSet::new();
834 let mut set = HashSet::new();
830 set.insert(HgPath::new(b"dir"));
835 set.insert(HgPathBuf::from_bytes(b"dir"));
831 assert_eq!(
836 assert_eq!(
832 matcher.visit_children_set(HgPath::new(b"")),
837 matcher.visit_children_set(HgPath::new(b"")),
833 VisitChildrenSet::Set(set)
838 VisitChildrenSet::Set(set)
834 );
839 );
835
840
836 let mut set = HashSet::new();
841 let mut set = HashSet::new();
837 set.insert(HgPath::new(b"subdir"));
842 set.insert(HgPathBuf::from_bytes(b"subdir"));
838 assert_eq!(
843 assert_eq!(
839 matcher.visit_children_set(HgPath::new(b"dir")),
844 matcher.visit_children_set(HgPath::new(b"dir")),
840 VisitChildrenSet::Set(set)
845 VisitChildrenSet::Set(set)
@@ -862,14 +867,14 b' mod tests {'
862 .unwrap();
867 .unwrap();
863
868
864 let mut set = HashSet::new();
869 let mut set = HashSet::new();
865 set.insert(HgPath::new(b"dir"));
870 set.insert(HgPathBuf::from_bytes(b"dir"));
866 assert_eq!(
871 assert_eq!(
867 matcher.visit_children_set(HgPath::new(b"")),
872 matcher.visit_children_set(HgPath::new(b"")),
868 VisitChildrenSet::Set(set)
873 VisitChildrenSet::Set(set)
869 );
874 );
870
875
871 let mut set = HashSet::new();
876 let mut set = HashSet::new();
872 set.insert(HgPath::new(b"subdir"));
877 set.insert(HgPathBuf::from_bytes(b"subdir"));
873 assert_eq!(
878 assert_eq!(
874 matcher.visit_children_set(HgPath::new(b"dir")),
879 matcher.visit_children_set(HgPath::new(b"dir")),
875 VisitChildrenSet::Set(set)
880 VisitChildrenSet::Set(set)
@@ -897,7 +902,7 b' mod tests {'
897 .unwrap();
902 .unwrap();
898
903
899 let mut set = HashSet::new();
904 let mut set = HashSet::new();
900 set.insert(HgPath::new(b"dir"));
905 set.insert(HgPathBuf::from_bytes(b"dir"));
901 assert_eq!(
906 assert_eq!(
902 matcher.visit_children_set(HgPath::new(b"")),
907 matcher.visit_children_set(HgPath::new(b"")),
903 VisitChildrenSet::Set(set)
908 VisitChildrenSet::Set(set)
@@ -169,7 +169,7 b' pub fn status_wrapper('
169 .collect();
169 .collect();
170
170
171 let files = files?;
171 let files = files?;
172 let matcher = FileMatcher::new(files.as_ref())
172 let matcher = FileMatcher::new(files)
173 .map_err(|e| PyErr::new::<ValueError, _>(py, e.to_string()))?;
173 .map_err(|e| PyErr::new::<ValueError, _>(py, e.to_string()))?;
174 dmap.with_status(
174 dmap.with_status(
175 &matcher,
175 &matcher,
General Comments 0
You need to be logged in to leave comments. Login now