##// END OF EJS Templates
rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`...
Raphaël Gomès -
r43742:a77d4fe3 default
parent child Browse files
Show More
@@ -0,0 +1,105 b''
1 // matchers.rs
2 //
3 // Copyright 2019 Raphaël Gomès <rgomes@octobus.net>
4 //
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.
7
8 //! Structs and types for matching files and directories.
9
10 use crate::utils::hg_path::{HgPath, HgPathBuf};
11 use std::collections::HashSet;
12
13 pub enum VisitChildrenSet {
14 /// Don't visit anything
15 Empty,
16 /// Only visit this directory
17 This,
18 /// Visit this directory and these subdirectories
19 /// TODO Should we implement a `NonEmptyHashSet`?
20 Set(HashSet<HgPathBuf>),
21 /// Visit this directory and all subdirectories
22 Recursive,
23 }
24
25 pub trait Matcher {
26 /// Explicitly listed files
27 fn file_set(&self) -> HashSet<&HgPath>;
28 /// Returns whether `filename` is in `file_set`
29 fn exact_match(&self, _filename: impl AsRef<HgPath>) -> bool {
30 false
31 }
32 /// Returns whether `filename` is matched by this matcher
33 fn matches(&self, _filename: impl AsRef<HgPath>) -> bool {
34 false
35 }
36 /// Decides whether a directory should be visited based on whether it
37 /// has potential matches in it or one of its subdirectories, and
38 /// potentially lists which subdirectories of that directory should be
39 /// visited. This is based on the match's primary, included, and excluded
40 /// patterns.
41 ///
42 /// # Example
43 ///
44 /// Assume matchers `['path:foo/bar', 'rootfilesin:qux']`, we would
45 /// return the following values (assuming the implementation of
46 /// visit_children_set is capable of recognizing this; some implementations
47 /// are not).
48 ///
49 /// ```ignore
50 /// '' -> {'foo', 'qux'}
51 /// 'baz' -> set()
52 /// 'foo' -> {'bar'}
53 /// // Ideally this would be `Recursive`, but since the prefix nature of
54 /// // matchers is applied to the entire matcher, we have to downgrade this
55 /// // to `This` due to the (yet to be implemented in Rust) non-prefix
56 /// // `RootFilesIn'-kind matcher being mixed in.
57 /// 'foo/bar' -> 'this'
58 /// 'qux' -> 'this'
59 /// ```
60 /// # Important
61 ///
62 /// Most matchers do not know if they're representing files or
63 /// directories. They see `['path:dir/f']` and don't know whether `f` is a
64 /// file or a directory, so `visit_children_set('dir')` for most matchers
65 /// will return `HashSet{ HgPath { "f" } }`, but if the matcher knows it's
66 /// a file (like the yet to be implemented in Rust `ExactMatcher` does),
67 /// it may return `VisitChildrenSet::This`.
68 /// Do not rely on the return being a `HashSet` indicating that there are
69 /// no files in this dir to investigate (or equivalently that if there are
70 /// files to investigate in 'dir' that it will always return
71 /// `VisitChildrenSet::This`).
72 fn visit_children_set(
73 &self,
74 _directory: impl AsRef<HgPath>,
75 ) -> VisitChildrenSet {
76 VisitChildrenSet::This
77 }
78 /// Matcher will match everything and `files_set()` will be empty:
79 /// optimization might be possible.
80 fn matches_everything(&self) -> bool {
81 false
82 }
83 /// Matcher will match exactly the files in `files_set()`: optimization
84 /// might be possible.
85 fn is_exact(&self) -> bool {
86 false
87 }
88 }
89
90 /// Matches everything.
91 #[derive(Debug)]
92 pub struct AlwaysMatcher;
93
94 impl Matcher for AlwaysMatcher {
95 fn file_set(&self) -> HashSet<&HgPath> {
96 HashSet::new()
97 }
98
99 fn visit_children_set(
100 &self,
101 _directory: impl AsRef<HgPath>,
102 ) -> VisitChildrenSet {
103 VisitChildrenSet::Recursive
104 }
105 }
@@ -1,151 +1,152 b''
1 1 // Copyright 2018 Georges Racinet <gracinet@anybox.fr>
2 2 //
3 3 // This software may be used and distributed according to the terms of the
4 4 // GNU General Public License version 2 or any later version.
5 5 mod ancestors;
6 6 pub mod dagops;
7 7 pub use ancestors::{AncestorsIterator, LazyAncestors, MissingAncestors};
8 8 mod dirstate;
9 9 pub mod discovery;
10 10 pub mod testing; // unconditionally built, for use from integration tests
11 11 pub use dirstate::{
12 12 dirs_multiset::{DirsMultiset, DirsMultisetIter},
13 13 dirstate_map::DirstateMap,
14 14 parsers::{pack_dirstate, parse_dirstate, PARENT_SIZE},
15 15 status::status,
16 16 CopyMap, CopyMapIter, DirstateEntry, DirstateParents, EntryState,
17 17 StateMap, StateMapIter,
18 18 };
19 19 mod filepatterns;
20 pub mod matchers;
20 21 pub mod utils;
21 22
22 23 use crate::utils::hg_path::HgPathBuf;
23 24 pub use filepatterns::{
24 25 build_single_regex, read_pattern_file, PatternSyntax, PatternTuple,
25 26 };
26 27
27 28 /// Mercurial revision numbers
28 29 ///
29 30 /// As noted in revlog.c, revision numbers are actually encoded in
30 31 /// 4 bytes, and are liberally converted to ints, whence the i32
31 32 pub type Revision = i32;
32 33
33 34 /// Marker expressing the absence of a parent
34 35 ///
35 36 /// Independently of the actual representation, `NULL_REVISION` is guaranteed
36 37 /// to be smaller that all existing revisions.
37 38 pub const NULL_REVISION: Revision = -1;
38 39
39 40 /// Same as `mercurial.node.wdirrev`
40 41 ///
41 42 /// This is also equal to `i32::max_value()`, but it's better to spell
42 43 /// it out explicitely, same as in `mercurial.node`
43 44 pub const WORKING_DIRECTORY_REVISION: Revision = 0x7fffffff;
44 45
45 46 /// The simplest expression of what we need of Mercurial DAGs.
46 47 pub trait Graph {
47 48 /// Return the two parents of the given `Revision`.
48 49 ///
49 50 /// Each of the parents can be independently `NULL_REVISION`
50 51 fn parents(&self, rev: Revision) -> Result<[Revision; 2], GraphError>;
51 52 }
52 53
53 54 pub type LineNumber = usize;
54 55
55 56 #[derive(Clone, Debug, PartialEq)]
56 57 pub enum GraphError {
57 58 ParentOutOfRange(Revision),
58 59 WorkingDirectoryUnsupported,
59 60 }
60 61
61 62 #[derive(Clone, Debug, PartialEq)]
62 63 pub enum DirstateParseError {
63 64 TooLittleData,
64 65 Overflow,
65 66 CorruptedEntry(String),
66 67 Damaged,
67 68 }
68 69
69 70 impl From<std::io::Error> for DirstateParseError {
70 71 fn from(e: std::io::Error) -> Self {
71 72 DirstateParseError::CorruptedEntry(e.to_string())
72 73 }
73 74 }
74 75
75 76 impl ToString for DirstateParseError {
76 77 fn to_string(&self) -> String {
77 78 use crate::DirstateParseError::*;
78 79 match self {
79 80 TooLittleData => "Too little data for dirstate.".to_string(),
80 81 Overflow => "Overflow in dirstate.".to_string(),
81 82 CorruptedEntry(e) => format!("Corrupted entry: {:?}.", e),
82 83 Damaged => "Dirstate appears to be damaged.".to_string(),
83 84 }
84 85 }
85 86 }
86 87
87 88 #[derive(Debug, PartialEq)]
88 89 pub enum DirstatePackError {
89 90 CorruptedEntry(String),
90 91 CorruptedParent,
91 92 BadSize(usize, usize),
92 93 }
93 94
94 95 impl From<std::io::Error> for DirstatePackError {
95 96 fn from(e: std::io::Error) -> Self {
96 97 DirstatePackError::CorruptedEntry(e.to_string())
97 98 }
98 99 }
99 100 #[derive(Debug, PartialEq)]
100 101 pub enum DirstateMapError {
101 102 PathNotFound(HgPathBuf),
102 103 EmptyPath,
103 104 }
104 105
105 106 pub enum DirstateError {
106 107 Parse(DirstateParseError),
107 108 Pack(DirstatePackError),
108 109 Map(DirstateMapError),
109 110 IO(std::io::Error),
110 111 }
111 112
112 113 impl From<DirstateParseError> for DirstateError {
113 114 fn from(e: DirstateParseError) -> Self {
114 115 DirstateError::Parse(e)
115 116 }
116 117 }
117 118
118 119 impl From<DirstatePackError> for DirstateError {
119 120 fn from(e: DirstatePackError) -> Self {
120 121 DirstateError::Pack(e)
121 122 }
122 123 }
123 124
124 125 #[derive(Debug)]
125 126 pub enum PatternError {
126 127 UnsupportedSyntax(String),
127 128 }
128 129
129 130 #[derive(Debug)]
130 131 pub enum PatternFileError {
131 132 IO(std::io::Error),
132 133 Pattern(PatternError, LineNumber),
133 134 }
134 135
135 136 impl From<std::io::Error> for PatternFileError {
136 137 fn from(e: std::io::Error) -> Self {
137 138 PatternFileError::IO(e)
138 139 }
139 140 }
140 141
141 142 impl From<DirstateMapError> for DirstateError {
142 143 fn from(e: DirstateMapError) -> Self {
143 144 DirstateError::Map(e)
144 145 }
145 146 }
146 147
147 148 impl From<std::io::Error> for DirstateError {
148 149 fn from(e: std::io::Error) -> Self {
149 150 DirstateError::IO(e)
150 151 }
151 152 }
General Comments 0
You need to be logged in to leave comments. Login now