##// 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 def _donormalize(patterns, default, root
202 202 kindpats.append((kind, pat, ''))
203 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 297 def __init__(self, root, cwd, normalize, patterns, include=None,
208 298 exclude=None, default='glob', exact=False, auditor=None,
209 299 ctx=None, listsubrepos=False, warn=None, badfn=None):
300 super(matcher, self).__init__(root, cwd, badfn)
210 301 if include is None:
211 302 include = []
212 303 if exclude is None:
213 304 exclude = []
214 305
215 self._root = root
216 self._cwd = cwd
217 self._files = [] # exact files and roots of patterns
218 306 self._anypats = bool(include or exclude)
219 307 self._always = False
220 308 self._pathrestricted = bool(include or exclude or patterns)
@@ -228,9 +316,6 class matcher(object):
228 316 # dirs are directories which are non-recursively included.
229 317 self._includedirs = set()
230 318
231 if badfn is not None:
232 self.bad = badfn
233
234 319 matchfns = []
235 320 if include:
236 321 kindpats = normalize(include, 'glob', root, cwd, auditor, warn)
@@ -281,70 +366,14 class matcher(object):
281 366
282 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 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 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 372 @propertycache
333 373 def _dirs(self):
334 374 return set(util.dirs(self._fileset)) | {'.'}
335 375
336 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 377 if self.prefix() and dir in self._fileset:
349 378 return 'all'
350 379 if dir in self._excluderoots:
@@ -363,25 +392,15 class matcher(object):
363 392 any(parentdir in self._fileset
364 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 395 def anypats(self):
371 '''Matcher uses patterns or include/exclude.'''
372 396 return self._anypats
373 397
374 398 def always(self):
375 '''Matcher will match everything and .files() will be empty
376 - optimization might be possible and necessary.'''
377 399 return self._always
378 400
379 401 def isexact(self):
380 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 404 def __repr__(self):
386 405 return ('<matcher files=%r, patterns=%r, includes=%r, excludes=%r>' %
387 406 (self._files, self.patternspat, self.includepat,
General Comments 0
You need to be logged in to leave comments. Login now