##// 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 // Copyright 2018 Georges Racinet <gracinet@anybox.fr>
1 // Copyright 2018 Georges Racinet <gracinet@anybox.fr>
2 //
2 //
3 // This software may be used and distributed according to the terms of the
3 // This software may be used and distributed according to the terms of the
4 // GNU General Public License version 2 or any later version.
4 // GNU General Public License version 2 or any later version.
5 mod ancestors;
5 mod ancestors;
6 pub mod dagops;
6 pub mod dagops;
7 pub use ancestors::{AncestorsIterator, LazyAncestors, MissingAncestors};
7 pub use ancestors::{AncestorsIterator, LazyAncestors, MissingAncestors};
8 mod dirstate;
8 mod dirstate;
9 pub mod discovery;
9 pub mod discovery;
10 pub mod testing; // unconditionally built, for use from integration tests
10 pub mod testing; // unconditionally built, for use from integration tests
11 pub use dirstate::{
11 pub use dirstate::{
12 dirs_multiset::{DirsMultiset, DirsMultisetIter},
12 dirs_multiset::{DirsMultiset, DirsMultisetIter},
13 dirstate_map::DirstateMap,
13 dirstate_map::DirstateMap,
14 parsers::{pack_dirstate, parse_dirstate, PARENT_SIZE},
14 parsers::{pack_dirstate, parse_dirstate, PARENT_SIZE},
15 status::status,
15 status::status,
16 CopyMap, CopyMapIter, DirstateEntry, DirstateParents, EntryState,
16 CopyMap, CopyMapIter, DirstateEntry, DirstateParents, EntryState,
17 StateMap, StateMapIter,
17 StateMap, StateMapIter,
18 };
18 };
19 mod filepatterns;
19 mod filepatterns;
20 pub mod matchers;
20 pub mod utils;
21 pub mod utils;
21
22
22 use crate::utils::hg_path::HgPathBuf;
23 use crate::utils::hg_path::HgPathBuf;
23 pub use filepatterns::{
24 pub use filepatterns::{
24 build_single_regex, read_pattern_file, PatternSyntax, PatternTuple,
25 build_single_regex, read_pattern_file, PatternSyntax, PatternTuple,
25 };
26 };
26
27
27 /// Mercurial revision numbers
28 /// Mercurial revision numbers
28 ///
29 ///
29 /// As noted in revlog.c, revision numbers are actually encoded in
30 /// As noted in revlog.c, revision numbers are actually encoded in
30 /// 4 bytes, and are liberally converted to ints, whence the i32
31 /// 4 bytes, and are liberally converted to ints, whence the i32
31 pub type Revision = i32;
32 pub type Revision = i32;
32
33
33 /// Marker expressing the absence of a parent
34 /// Marker expressing the absence of a parent
34 ///
35 ///
35 /// Independently of the actual representation, `NULL_REVISION` is guaranteed
36 /// Independently of the actual representation, `NULL_REVISION` is guaranteed
36 /// to be smaller that all existing revisions.
37 /// to be smaller that all existing revisions.
37 pub const NULL_REVISION: Revision = -1;
38 pub const NULL_REVISION: Revision = -1;
38
39
39 /// Same as `mercurial.node.wdirrev`
40 /// Same as `mercurial.node.wdirrev`
40 ///
41 ///
41 /// This is also equal to `i32::max_value()`, but it's better to spell
42 /// This is also equal to `i32::max_value()`, but it's better to spell
42 /// it out explicitely, same as in `mercurial.node`
43 /// it out explicitely, same as in `mercurial.node`
43 pub const WORKING_DIRECTORY_REVISION: Revision = 0x7fffffff;
44 pub const WORKING_DIRECTORY_REVISION: Revision = 0x7fffffff;
44
45
45 /// The simplest expression of what we need of Mercurial DAGs.
46 /// The simplest expression of what we need of Mercurial DAGs.
46 pub trait Graph {
47 pub trait Graph {
47 /// Return the two parents of the given `Revision`.
48 /// Return the two parents of the given `Revision`.
48 ///
49 ///
49 /// Each of the parents can be independently `NULL_REVISION`
50 /// Each of the parents can be independently `NULL_REVISION`
50 fn parents(&self, rev: Revision) -> Result<[Revision; 2], GraphError>;
51 fn parents(&self, rev: Revision) -> Result<[Revision; 2], GraphError>;
51 }
52 }
52
53
53 pub type LineNumber = usize;
54 pub type LineNumber = usize;
54
55
55 #[derive(Clone, Debug, PartialEq)]
56 #[derive(Clone, Debug, PartialEq)]
56 pub enum GraphError {
57 pub enum GraphError {
57 ParentOutOfRange(Revision),
58 ParentOutOfRange(Revision),
58 WorkingDirectoryUnsupported,
59 WorkingDirectoryUnsupported,
59 }
60 }
60
61
61 #[derive(Clone, Debug, PartialEq)]
62 #[derive(Clone, Debug, PartialEq)]
62 pub enum DirstateParseError {
63 pub enum DirstateParseError {
63 TooLittleData,
64 TooLittleData,
64 Overflow,
65 Overflow,
65 CorruptedEntry(String),
66 CorruptedEntry(String),
66 Damaged,
67 Damaged,
67 }
68 }
68
69
69 impl From<std::io::Error> for DirstateParseError {
70 impl From<std::io::Error> for DirstateParseError {
70 fn from(e: std::io::Error) -> Self {
71 fn from(e: std::io::Error) -> Self {
71 DirstateParseError::CorruptedEntry(e.to_string())
72 DirstateParseError::CorruptedEntry(e.to_string())
72 }
73 }
73 }
74 }
74
75
75 impl ToString for DirstateParseError {
76 impl ToString for DirstateParseError {
76 fn to_string(&self) -> String {
77 fn to_string(&self) -> String {
77 use crate::DirstateParseError::*;
78 use crate::DirstateParseError::*;
78 match self {
79 match self {
79 TooLittleData => "Too little data for dirstate.".to_string(),
80 TooLittleData => "Too little data for dirstate.".to_string(),
80 Overflow => "Overflow in dirstate.".to_string(),
81 Overflow => "Overflow in dirstate.".to_string(),
81 CorruptedEntry(e) => format!("Corrupted entry: {:?}.", e),
82 CorruptedEntry(e) => format!("Corrupted entry: {:?}.", e),
82 Damaged => "Dirstate appears to be damaged.".to_string(),
83 Damaged => "Dirstate appears to be damaged.".to_string(),
83 }
84 }
84 }
85 }
85 }
86 }
86
87
87 #[derive(Debug, PartialEq)]
88 #[derive(Debug, PartialEq)]
88 pub enum DirstatePackError {
89 pub enum DirstatePackError {
89 CorruptedEntry(String),
90 CorruptedEntry(String),
90 CorruptedParent,
91 CorruptedParent,
91 BadSize(usize, usize),
92 BadSize(usize, usize),
92 }
93 }
93
94
94 impl From<std::io::Error> for DirstatePackError {
95 impl From<std::io::Error> for DirstatePackError {
95 fn from(e: std::io::Error) -> Self {
96 fn from(e: std::io::Error) -> Self {
96 DirstatePackError::CorruptedEntry(e.to_string())
97 DirstatePackError::CorruptedEntry(e.to_string())
97 }
98 }
98 }
99 }
99 #[derive(Debug, PartialEq)]
100 #[derive(Debug, PartialEq)]
100 pub enum DirstateMapError {
101 pub enum DirstateMapError {
101 PathNotFound(HgPathBuf),
102 PathNotFound(HgPathBuf),
102 EmptyPath,
103 EmptyPath,
103 }
104 }
104
105
105 pub enum DirstateError {
106 pub enum DirstateError {
106 Parse(DirstateParseError),
107 Parse(DirstateParseError),
107 Pack(DirstatePackError),
108 Pack(DirstatePackError),
108 Map(DirstateMapError),
109 Map(DirstateMapError),
109 IO(std::io::Error),
110 IO(std::io::Error),
110 }
111 }
111
112
112 impl From<DirstateParseError> for DirstateError {
113 impl From<DirstateParseError> for DirstateError {
113 fn from(e: DirstateParseError) -> Self {
114 fn from(e: DirstateParseError) -> Self {
114 DirstateError::Parse(e)
115 DirstateError::Parse(e)
115 }
116 }
116 }
117 }
117
118
118 impl From<DirstatePackError> for DirstateError {
119 impl From<DirstatePackError> for DirstateError {
119 fn from(e: DirstatePackError) -> Self {
120 fn from(e: DirstatePackError) -> Self {
120 DirstateError::Pack(e)
121 DirstateError::Pack(e)
121 }
122 }
122 }
123 }
123
124
124 #[derive(Debug)]
125 #[derive(Debug)]
125 pub enum PatternError {
126 pub enum PatternError {
126 UnsupportedSyntax(String),
127 UnsupportedSyntax(String),
127 }
128 }
128
129
129 #[derive(Debug)]
130 #[derive(Debug)]
130 pub enum PatternFileError {
131 pub enum PatternFileError {
131 IO(std::io::Error),
132 IO(std::io::Error),
132 Pattern(PatternError, LineNumber),
133 Pattern(PatternError, LineNumber),
133 }
134 }
134
135
135 impl From<std::io::Error> for PatternFileError {
136 impl From<std::io::Error> for PatternFileError {
136 fn from(e: std::io::Error) -> Self {
137 fn from(e: std::io::Error) -> Self {
137 PatternFileError::IO(e)
138 PatternFileError::IO(e)
138 }
139 }
139 }
140 }
140
141
141 impl From<DirstateMapError> for DirstateError {
142 impl From<DirstateMapError> for DirstateError {
142 fn from(e: DirstateMapError) -> Self {
143 fn from(e: DirstateMapError) -> Self {
143 DirstateError::Map(e)
144 DirstateError::Map(e)
144 }
145 }
145 }
146 }
146
147
147 impl From<std::io::Error> for DirstateError {
148 impl From<std::io::Error> for DirstateError {
148 fn from(e: std::io::Error) -> Self {
149 fn from(e: std::io::Error) -> Self {
149 DirstateError::IO(e)
150 DirstateError::IO(e)
150 }
151 }
151 }
152 }
General Comments 0
You need to be logged in to leave comments. Login now