annotate rust/hg-core/src/matchers.rs @ 43832:1bb4e9b02984

rust-matchers: improve `Matcher` trait ergonomics `VisitChildrenSet` has no need to own the set, this will save allocations. The `file_set` return type change is motivated by both ergonomics and... being able to compile code. The `AlwaysMatcher` does not store a `file_set`, which requires it to return an owned `HashSet`, which in turn would change our return type to `Cow<&HgPath>` (lifetimes omitted). This is both un-ergonomic and troublesome for more complex lifetime issues (especially with the upcoming `FileMatcher` in the following patch). Differential Revision: https://phab.mercurial-scm.org/D7525
author Raphaël Gomès <rgomes@octobus.net>
date Fri, 29 Nov 2019 18:33:56 +0100
parents 27c25c0dc967
children 542c8b277261
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
43438
a77d4fe347a4 rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
1 // matchers.rs
a77d4fe347a4 rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
2 //
a77d4fe347a4 rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
3 // Copyright 2019 Raphaël Gomès <rgomes@octobus.net>
a77d4fe347a4 rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
4 //
a77d4fe347a4 rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
5 // This software may be used and distributed according to the terms of the
a77d4fe347a4 rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
6 // GNU General Public License version 2 or any later version.
a77d4fe347a4 rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
7
a77d4fe347a4 rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
8 //! Structs and types for matching files and directories.
a77d4fe347a4 rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
9
a77d4fe347a4 rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
10 use crate::utils::hg_path::{HgPath, HgPathBuf};
a77d4fe347a4 rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
11 use std::collections::HashSet;
a77d4fe347a4 rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
12
43832
1bb4e9b02984 rust-matchers: improve `Matcher` trait ergonomics
Raphaël Gomès <rgomes@octobus.net>
parents: 43611
diff changeset
13 pub enum VisitChildrenSet<'a> {
43438
a77d4fe347a4 rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
14 /// Don't visit anything
a77d4fe347a4 rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
15 Empty,
a77d4fe347a4 rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
16 /// Only visit this directory
a77d4fe347a4 rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
17 This,
a77d4fe347a4 rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
18 /// Visit this directory and these subdirectories
a77d4fe347a4 rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
19 /// TODO Should we implement a `NonEmptyHashSet`?
43832
1bb4e9b02984 rust-matchers: improve `Matcher` trait ergonomics
Raphaël Gomès <rgomes@octobus.net>
parents: 43611
diff changeset
20 Set(HashSet<&'a HgPath>),
43438
a77d4fe347a4 rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
21 /// Visit this directory and all subdirectories
a77d4fe347a4 rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
22 Recursive,
a77d4fe347a4 rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
23 }
a77d4fe347a4 rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
24
a77d4fe347a4 rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
25 pub trait Matcher {
a77d4fe347a4 rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
26 /// Explicitly listed files
43832
1bb4e9b02984 rust-matchers: improve `Matcher` trait ergonomics
Raphaël Gomès <rgomes@octobus.net>
parents: 43611
diff changeset
27 fn file_set(&self) -> Option<&HashSet<&HgPath>>;
43438
a77d4fe347a4 rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
28 /// Returns whether `filename` is in `file_set`
43611
27c25c0dc967 rust-matchers: remove default implementations for `Matcher` trait
Raphaël Gomès <rgomes@octobus.net>
parents: 43438
diff changeset
29 fn exact_match(&self, filename: impl AsRef<HgPath>) -> bool;
43438
a77d4fe347a4 rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
30 /// Returns whether `filename` is matched by this matcher
43611
27c25c0dc967 rust-matchers: remove default implementations for `Matcher` trait
Raphaël Gomès <rgomes@octobus.net>
parents: 43438
diff changeset
31 fn matches(&self, filename: impl AsRef<HgPath>) -> bool;
43438
a77d4fe347a4 rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
32 /// Decides whether a directory should be visited based on whether it
a77d4fe347a4 rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
33 /// has potential matches in it or one of its subdirectories, and
a77d4fe347a4 rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
34 /// potentially lists which subdirectories of that directory should be
a77d4fe347a4 rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
35 /// visited. This is based on the match's primary, included, and excluded
a77d4fe347a4 rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
36 /// patterns.
a77d4fe347a4 rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
37 ///
a77d4fe347a4 rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
38 /// # Example
a77d4fe347a4 rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
39 ///
a77d4fe347a4 rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
40 /// Assume matchers `['path:foo/bar', 'rootfilesin:qux']`, we would
a77d4fe347a4 rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
41 /// return the following values (assuming the implementation of
a77d4fe347a4 rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
42 /// visit_children_set is capable of recognizing this; some implementations
a77d4fe347a4 rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
43 /// are not).
a77d4fe347a4 rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
44 ///
a77d4fe347a4 rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
45 /// ```ignore
a77d4fe347a4 rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
46 /// '' -> {'foo', 'qux'}
a77d4fe347a4 rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
47 /// 'baz' -> set()
a77d4fe347a4 rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
48 /// 'foo' -> {'bar'}
a77d4fe347a4 rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
49 /// // Ideally this would be `Recursive`, but since the prefix nature of
a77d4fe347a4 rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
50 /// // matchers is applied to the entire matcher, we have to downgrade this
a77d4fe347a4 rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
51 /// // to `This` due to the (yet to be implemented in Rust) non-prefix
a77d4fe347a4 rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
52 /// // `RootFilesIn'-kind matcher being mixed in.
a77d4fe347a4 rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
53 /// 'foo/bar' -> 'this'
a77d4fe347a4 rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
54 /// 'qux' -> 'this'
a77d4fe347a4 rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
55 /// ```
a77d4fe347a4 rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
56 /// # Important
a77d4fe347a4 rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
57 ///
a77d4fe347a4 rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
58 /// Most matchers do not know if they're representing files or
a77d4fe347a4 rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
59 /// directories. They see `['path:dir/f']` and don't know whether `f` is a
a77d4fe347a4 rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
60 /// file or a directory, so `visit_children_set('dir')` for most matchers
a77d4fe347a4 rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
61 /// will return `HashSet{ HgPath { "f" } }`, but if the matcher knows it's
a77d4fe347a4 rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
62 /// a file (like the yet to be implemented in Rust `ExactMatcher` does),
a77d4fe347a4 rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
63 /// it may return `VisitChildrenSet::This`.
a77d4fe347a4 rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
64 /// Do not rely on the return being a `HashSet` indicating that there are
a77d4fe347a4 rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
65 /// no files in this dir to investigate (or equivalently that if there are
a77d4fe347a4 rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
66 /// files to investigate in 'dir' that it will always return
a77d4fe347a4 rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
67 /// `VisitChildrenSet::This`).
a77d4fe347a4 rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
68 fn visit_children_set(
a77d4fe347a4 rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
69 &self,
43611
27c25c0dc967 rust-matchers: remove default implementations for `Matcher` trait
Raphaël Gomès <rgomes@octobus.net>
parents: 43438
diff changeset
70 directory: impl AsRef<HgPath>,
27c25c0dc967 rust-matchers: remove default implementations for `Matcher` trait
Raphaël Gomès <rgomes@octobus.net>
parents: 43438
diff changeset
71 ) -> VisitChildrenSet;
43438
a77d4fe347a4 rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
72 /// Matcher will match everything and `files_set()` will be empty:
a77d4fe347a4 rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
73 /// optimization might be possible.
43611
27c25c0dc967 rust-matchers: remove default implementations for `Matcher` trait
Raphaël Gomès <rgomes@octobus.net>
parents: 43438
diff changeset
74 fn matches_everything(&self) -> bool;
43438
a77d4fe347a4 rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
75 /// Matcher will match exactly the files in `files_set()`: optimization
a77d4fe347a4 rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
76 /// might be possible.
43611
27c25c0dc967 rust-matchers: remove default implementations for `Matcher` trait
Raphaël Gomès <rgomes@octobus.net>
parents: 43438
diff changeset
77 fn is_exact(&self) -> bool;
43438
a77d4fe347a4 rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
78 }
a77d4fe347a4 rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
79
a77d4fe347a4 rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
80 /// Matches everything.
a77d4fe347a4 rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
81 #[derive(Debug)]
a77d4fe347a4 rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
82 pub struct AlwaysMatcher;
a77d4fe347a4 rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
83
a77d4fe347a4 rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
84 impl Matcher for AlwaysMatcher {
43832
1bb4e9b02984 rust-matchers: improve `Matcher` trait ergonomics
Raphaël Gomès <rgomes@octobus.net>
parents: 43611
diff changeset
85 fn file_set(&self) -> Option<&HashSet<&HgPath>> {
1bb4e9b02984 rust-matchers: improve `Matcher` trait ergonomics
Raphaël Gomès <rgomes@octobus.net>
parents: 43611
diff changeset
86 None
43438
a77d4fe347a4 rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
87 }
43611
27c25c0dc967 rust-matchers: remove default implementations for `Matcher` trait
Raphaël Gomès <rgomes@octobus.net>
parents: 43438
diff changeset
88 fn exact_match(&self, _filename: impl AsRef<HgPath>) -> bool {
27c25c0dc967 rust-matchers: remove default implementations for `Matcher` trait
Raphaël Gomès <rgomes@octobus.net>
parents: 43438
diff changeset
89 false
27c25c0dc967 rust-matchers: remove default implementations for `Matcher` trait
Raphaël Gomès <rgomes@octobus.net>
parents: 43438
diff changeset
90 }
27c25c0dc967 rust-matchers: remove default implementations for `Matcher` trait
Raphaël Gomès <rgomes@octobus.net>
parents: 43438
diff changeset
91 fn matches(&self, _filename: impl AsRef<HgPath>) -> bool {
27c25c0dc967 rust-matchers: remove default implementations for `Matcher` trait
Raphaël Gomès <rgomes@octobus.net>
parents: 43438
diff changeset
92 true
27c25c0dc967 rust-matchers: remove default implementations for `Matcher` trait
Raphaël Gomès <rgomes@octobus.net>
parents: 43438
diff changeset
93 }
43438
a77d4fe347a4 rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
94 fn visit_children_set(
a77d4fe347a4 rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
95 &self,
a77d4fe347a4 rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
96 _directory: impl AsRef<HgPath>,
a77d4fe347a4 rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
97 ) -> VisitChildrenSet {
a77d4fe347a4 rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
98 VisitChildrenSet::Recursive
a77d4fe347a4 rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
99 }
43611
27c25c0dc967 rust-matchers: remove default implementations for `Matcher` trait
Raphaël Gomès <rgomes@octobus.net>
parents: 43438
diff changeset
100 fn matches_everything(&self) -> bool {
27c25c0dc967 rust-matchers: remove default implementations for `Matcher` trait
Raphaël Gomès <rgomes@octobus.net>
parents: 43438
diff changeset
101 true
27c25c0dc967 rust-matchers: remove default implementations for `Matcher` trait
Raphaël Gomès <rgomes@octobus.net>
parents: 43438
diff changeset
102 }
27c25c0dc967 rust-matchers: remove default implementations for `Matcher` trait
Raphaël Gomès <rgomes@octobus.net>
parents: 43438
diff changeset
103 fn is_exact(&self) -> bool {
27c25c0dc967 rust-matchers: remove default implementations for `Matcher` trait
Raphaël Gomès <rgomes@octobus.net>
parents: 43438
diff changeset
104 false
27c25c0dc967 rust-matchers: remove default implementations for `Matcher` trait
Raphaël Gomès <rgomes@octobus.net>
parents: 43438
diff changeset
105 }
43438
a77d4fe347a4 rust-matchers: add `Matcher` trait and implement `AlwaysMatcher`
Raphaël Gomès <rgomes@octobus.net>
parents:
diff changeset
106 }