blob: eb12f9b0dd8d253dfe7e742bdd34c9a461e1de94 [file] [log] [blame]
Maru Newby3fe5f852015-01-13 04:22:14 +00001# Copyright 2015 Red Hat, Inc.
2#
3# Licensed under the Apache License, Version 2.0 (the "License"); you may
4# not use this file except in compliance with the License. You may obtain
5# a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12# License for the specific language governing permissions and limitations
13# under the License.
14
15"""
16This module defines classes used in matching changes based on job
17configuration.
18"""
19
20import re
21
22
23class AbstractChangeMatcher(object):
24
25 def __init__(self, regex):
26 self._regex = regex
27 self.regex = re.compile(regex)
28
29 def matches(self, change):
30 """Return a boolean indication of whether change matches
31 implementation-specific criteria.
32 """
33 raise NotImplementedError()
34
35 def copy(self):
36 return self.__class__(self._regex)
37
James E. Blaira7f51ca2017-02-07 16:01:26 -080038 def __deepcopy__(self, memo):
39 return self.copy()
40
Maru Newby3fe5f852015-01-13 04:22:14 +000041 def __eq__(self, other):
42 return str(self) == str(other)
43
James E. Blaira7f51ca2017-02-07 16:01:26 -080044 def __ne__(self, other):
45 return not self.__eq__(other)
46
Maru Newby3fe5f852015-01-13 04:22:14 +000047 def __str__(self):
48 return '{%s:%s}' % (self.__class__.__name__, self._regex)
49
50 def __repr__(self):
51 return '<%s %s>' % (self.__class__.__name__, self._regex)
52
53
54class ProjectMatcher(AbstractChangeMatcher):
55
56 def matches(self, change):
57 return self.regex.match(str(change.project))
58
59
60class BranchMatcher(AbstractChangeMatcher):
61
62 def matches(self, change):
David Shrewsburyf6dc1762017-10-02 13:34:37 -040063 if hasattr(change, 'branch'):
64 if self.regex.match(change.branch):
65 return True
66 return False
67 if self.regex.match(change.ref):
68 return True
69 return False
Maru Newby3fe5f852015-01-13 04:22:14 +000070
71
James E. Blair1edfd972017-12-01 15:54:24 -080072class ImpliedBranchMatcher(AbstractChangeMatcher):
73 """
74 A branch matcher that only considers branch refs, and always
75 succeeds on other types (e.g., tags).
76 """
77
78 def matches(self, change):
79 if hasattr(change, 'branch'):
80 if self.regex.match(change.branch):
81 return True
82 return False
83 return True
84
85
Maru Newby3fe5f852015-01-13 04:22:14 +000086class FileMatcher(AbstractChangeMatcher):
87
88 def matches(self, change):
89 if not hasattr(change, 'files'):
90 return False
91 for file_ in change.files:
92 if self.regex.match(file_):
93 return True
94 return False
95
96
97class AbstractMatcherCollection(AbstractChangeMatcher):
98
99 def __init__(self, matchers):
100 self.matchers = matchers
101
102 def __eq__(self, other):
103 return str(self) == str(other)
104
105 def __str__(self):
106 return '{%s:%s}' % (self.__class__.__name__,
107 ','.join([str(x) for x in self.matchers]))
108
109 def __repr__(self):
110 return '<%s>' % self.__class__.__name__
111
112 def copy(self):
113 return self.__class__(self.matchers[:])
114
115
116class MatchAllFiles(AbstractMatcherCollection):
117
118 commit_regex = re.compile('^/COMMIT_MSG$')
119
120 @property
121 def regexes(self):
122 for matcher in self.matchers:
123 yield matcher.regex
124 yield self.commit_regex
125
126 def matches(self, change):
Jan Hruban570d01c2016-03-10 21:51:32 +0100127 if not (hasattr(change, 'files') and change.files):
128 return False
129 if len(change.files) == 1 and self.commit_regex.match(change.files[0]):
Maru Newby3fe5f852015-01-13 04:22:14 +0000130 return False
131 for file_ in change.files:
132 matched_file = False
133 for regex in self.regexes:
134 if regex.match(file_):
135 matched_file = True
136 break
137 if not matched_file:
138 return False
139 return True
140
141
142class MatchAll(AbstractMatcherCollection):
143
144 def matches(self, change):
145 for matcher in self.matchers:
146 if not matcher.matches(change):
147 return False
148 return True
149
150
151class MatchAny(AbstractMatcherCollection):
152
153 def matches(self, change):
154 for matcher in self.matchers:
155 if matcher.matches(change):
156 return True
157 return False