##// END OF EJS Templates
match: extract base class for matchers...
Martin von Zweigbergk -
r32454:a04bc552 default
parent child Browse files
Show More
@@ -202,19 +202,107 b' def _donormalize(patterns, default, root'
202 kindpats.append((kind, pat, ''))
202 kindpats.append((kind, pat, ''))
203 return kindpats
203 return kindpats
204
204
205 class matcher(object):
205 class basematcher(object):
206
207 def __init__(self, root, cwd, badfn=None):
208 self._root = root
209 self._cwd = cwd
210 if badfn is not None:
211 self.bad = badfn
212 self._files = [] # exact files and roots of patterns
213 self.matchfn = lambda f: False
214
215 def __call__(self, fn):
216 return self.matchfn(fn)
217 def __iter__(self):
218 for f in self._files:
219 yield f
220 # Callbacks related to how the matcher is used by dirstate.walk.
221 # Subscribers to these events must monkeypatch the matcher object.
222 def bad(self, f, msg):
223 '''Callback from dirstate.walk for each explicit file that can't be
224 found/accessed, with an error message.'''
225 pass
226
227 # If an explicitdir is set, it will be called when an explicitly listed
228 # directory is visited.
229 explicitdir = None
230
231 # If an traversedir is set, it will be called when a directory discovered
232 # by recursive traversal is visited.
233 traversedir = None
234
235 def abs(self, f):
236 '''Convert a repo path back to path that is relative to the root of the
237 matcher.'''
238 return f
239
240 def rel(self, f):
241 '''Convert repo path back to path that is relative to cwd of matcher.'''
242 return util.pathto(self._root, self._cwd, f)
243
244 def uipath(self, f):
245 '''Convert repo path to a display path. If patterns or -I/-X were used
246 to create this matcher, the display path will be relative to cwd.
247 Otherwise it is relative to the root of the repo.'''
248 return self.rel(f)
249
250 def files(self):
251 '''Explicitly listed files or patterns or roots:
252 if no patterns or .always(): empty list,
253 if exact: list exact files,
254 if not .anypats(): list all files and dirs,
255 else: optimal roots'''
256 return self._files
257
258 @propertycache
259 def _fileset(self):
260 return set(self._files)
261
262 def exact(self, f):
263 '''Returns True if f is in .files().'''
264 return f in self._fileset
265
266 def visitdir(self, dir):
267 '''Decides whether a directory should be visited based on whether it
268 has potential matches in it or one of its subdirectories. This is
269 based on the match's primary, included, and excluded patterns.
270
271 Returns the string 'all' if the given directory and all subdirectories
272 should be visited. Otherwise returns True or False indicating whether
273 the given directory should be visited.
274
275 This function's behavior is undefined if it has returned False for
276 one of the dir's parent directories.
277 '''
278 return False
279
280 def anypats(self):
281 '''Matcher uses patterns or include/exclude.'''
282 return False
283
284 def always(self):
285 '''Matcher will match everything and .files() will be empty
286 - optimization might be possible and necessary.'''
287 return False
288
289 def isexact(self):
290 return False
291
292 def prefix(self):
293 return not self.always() and not self.isexact() and not self.anypats()
294
295 class matcher(basematcher):
206
296
207 def __init__(self, root, cwd, normalize, patterns, include=None,
297 def __init__(self, root, cwd, normalize, patterns, include=None,
208 exclude=None, default='glob', exact=False, auditor=None,
298 exclude=None, default='glob', exact=False, auditor=None,
209 ctx=None, listsubrepos=False, warn=None, badfn=None):
299 ctx=None, listsubrepos=False, warn=None, badfn=None):
300 super(matcher, self).__init__(root, cwd, badfn)
210 if include is None:
301 if include is None:
211 include = []
302 include = []
212 if exclude is None:
303 if exclude is None:
213 exclude = []
304 exclude = []
214
305
215 self._root = root
216 self._cwd = cwd
217 self._files = [] # exact files and roots of patterns
218 self._anypats = bool(include or exclude)
306 self._anypats = bool(include or exclude)
219 self._always = False
307 self._always = False
220 self._pathrestricted = bool(include or exclude or patterns)
308 self._pathrestricted = bool(include or exclude or patterns)
@@ -228,9 +316,6 b' class matcher(object):'
228 # dirs are directories which are non-recursively included.
316 # dirs are directories which are non-recursively included.
229 self._includedirs = set()
317 self._includedirs = set()
230
318
231 if badfn is not None:
232 self.bad = badfn
233
234 matchfns = []
319 matchfns = []
235 if include:
320 if include:
236 kindpats = normalize(include, 'glob', root, cwd, auditor, warn)
321 kindpats = normalize(include, 'glob', root, cwd, auditor, warn)
@@ -281,70 +366,14 b' class matcher(object):'
281
366
282 self.matchfn = m
367 self.matchfn = m
283
368
284 def __call__(self, fn):
285 return self.matchfn(fn)
286 def __iter__(self):
287 for f in self._files:
288 yield f
289
290 # Callbacks related to how the matcher is used by dirstate.walk.
291 # Subscribers to these events must monkeypatch the matcher object.
292 def bad(self, f, msg):
293 '''Callback from dirstate.walk for each explicit file that can't be
294 found/accessed, with an error message.'''
295 pass
296
297 # If an explicitdir is set, it will be called when an explicitly listed
298 # directory is visited.
299 explicitdir = None
300
301 # If an traversedir is set, it will be called when a directory discovered
302 # by recursive traversal is visited.
303 traversedir = None
304
305 def abs(self, f):
306 '''Convert a repo path back to path that is relative to the root of the
307 matcher.'''
308 return f
309
310 def rel(self, f):
311 '''Convert repo path back to path that is relative to cwd of matcher.'''
312 return util.pathto(self._root, self._cwd, f)
313
314 def uipath(self, f):
369 def uipath(self, f):
315 '''Convert repo path to a display path. If patterns or -I/-X were used
316 to create this matcher, the display path will be relative to cwd.
317 Otherwise it is relative to the root of the repo.'''
318 return (self._pathrestricted and self.rel(f)) or self.abs(f)
370 return (self._pathrestricted and self.rel(f)) or self.abs(f)
319
371
320 def files(self):
321 '''Explicitly listed files or patterns or roots:
322 if no patterns or .always(): empty list,
323 if exact: list exact files,
324 if not .anypats(): list all files and dirs,
325 else: optimal roots'''
326 return self._files
327
328 @propertycache
329 def _fileset(self):
330 return set(self._files)
331
332 @propertycache
372 @propertycache
333 def _dirs(self):
373 def _dirs(self):
334 return set(util.dirs(self._fileset)) | {'.'}
374 return set(util.dirs(self._fileset)) | {'.'}
335
375
336 def visitdir(self, dir):
376 def visitdir(self, dir):
337 '''Decides whether a directory should be visited based on whether it
338 has potential matches in it or one of its subdirectories. This is
339 based on the match's primary, included, and excluded patterns.
340
341 Returns the string 'all' if the given directory and all subdirectories
342 should be visited. Otherwise returns True or False indicating whether
343 the given directory should be visited.
344
345 This function's behavior is undefined if it has returned False for
346 one of the dir's parent directories.
347 '''
348 if self.prefix() and dir in self._fileset:
377 if self.prefix() and dir in self._fileset:
349 return 'all'
378 return 'all'
350 if dir in self._excluderoots:
379 if dir in self._excluderoots:
@@ -363,25 +392,15 b' class matcher(object):'
363 any(parentdir in self._fileset
392 any(parentdir in self._fileset
364 for parentdir in util.finddirs(dir)))
393 for parentdir in util.finddirs(dir)))
365
394
366 def exact(self, f):
367 '''Returns True if f is in .files().'''
368 return f in self._fileset
369
370 def anypats(self):
395 def anypats(self):
371 '''Matcher uses patterns or include/exclude.'''
372 return self._anypats
396 return self._anypats
373
397
374 def always(self):
398 def always(self):
375 '''Matcher will match everything and .files() will be empty
376 - optimization might be possible and necessary.'''
377 return self._always
399 return self._always
378
400
379 def isexact(self):
401 def isexact(self):
380 return self.matchfn == self.exact
402 return self.matchfn == self.exact
381
403
382 def prefix(self):
383 return not self.always() and not self.isexact() and not self.anypats()
384
385 def __repr__(self):
404 def __repr__(self):
386 return ('<matcher files=%r, patterns=%r, includes=%r, excludes=%r>' %
405 return ('<matcher files=%r, patterns=%r, includes=%r, excludes=%r>' %
387 (self._files, self.patternspat, self.includepat,
406 (self._files, self.patternspat, self.includepat,
General Comments 0
You need to be logged in to leave comments. Login now