comparison mercurial/fileset.py @ 14678:5ef7b87530f6

fileset: prescan parse tree to optimize status usage We only call status if needed to avoid walking the working directory or comparing manifests. Similarly, we scan for whether unknown or ignored files are mentioned so we can include them.
author Matt Mackall <mpm@selenic.com>
date Sat, 18 Jun 2011 16:53:49 -0500
parents 2a758ffc821e
children e141e1cee0cc
comparison
equal deleted inserted replaced
14677:2a758ffc821e 14678:5ef7b87530f6
202 class matchctx(object): 202 class matchctx(object):
203 def __init__(self, ctx, subset=None, status=None): 203 def __init__(self, ctx, subset=None, status=None):
204 self.ctx = ctx 204 self.ctx = ctx
205 self.subset = subset 205 self.subset = subset
206 self._status = status 206 self._status = status
207 if status is None:
208 # desperately wants optimizing
209 r = self.ctx._repo
210 self._status = r.status(self.ctx.p1(), self.ctx,
211 unknown=True, ignored=True, clean=True)
212 if subset is None:
213 self.subset = []
214 for c in self._status:
215 self.subset.extend(c)
216 def status(self): 207 def status(self):
217 if not self._status:
218 r = self.ctx._repo
219 # also wants optimizing
220 self._status = r.status(self.ctx.p1(), self.ctx,
221 unknown=True, ignored=True, clean=True)
222 return self._status 208 return self._status
223 def matcher(self, patterns): 209 def matcher(self, patterns):
224 return self.ctx.match(patterns) 210 return self.ctx.match(patterns)
225 def filter(self, files): 211 def filter(self, files):
226 return [f for f in files if f in self.subset] 212 return [f for f in files if f in self.subset]
227 def narrow(self, files): 213 def narrow(self, files):
228 return matchctx(self.ctx, self.filter(files), self._status) 214 return matchctx(self.ctx, self.filter(files), self._status)
229 215
216 def _intree(funcs, tree):
217 if isinstance(tree, tuple):
218 if tree[0] == 'func' and tree[1][0] == 'symbol':
219 if tree[1][1] in funcs:
220 return True
221 for s in tree[1:]:
222 if _intree(funcs, s):
223 return True
224 return False
225
230 def getfileset(ctx, expr): 226 def getfileset(ctx, expr):
231 tree, pos = parse(expr) 227 tree, pos = parse(expr)
232 if (pos != len(expr)): 228 if (pos != len(expr)):
233 raise error.ParseError("invalid token", pos) 229 raise error.ParseError("invalid token", pos)
234 return getset(matchctx(ctx), tree) 230
231 # do we need status info?
232 if _intree(['modified', 'added', 'removed', 'deleted',
233 'unknown', 'ignored', 'clean'], tree):
234 unknown = _intree(['unknown'], tree)
235 ignored = _intree(['ignored'], tree)
236
237 r = ctx._repo
238 status = r.status(ctx.p1(), ctx,
239 unknown=unknown, ignored=ignored, clean=True)
240 subset = []
241 for c in status:
242 subset.extend(c)
243 else:
244 status = None
245 subset = ctx.walk(ctx.match([]))
246
247 return getset(matchctx(ctx, subset, status), tree)