Mercurial > hg
comparison hgext/graphlog.py @ 16161:5a627b49b4d9
graphlog: paths/-I/-X handling requires a new revset
The filtering logic of match objects cannot be reproduced with the existing
revsets as it operates at changeset files level. A changeset touching "a" and
"b" is matched by "-I a -X b" but not by "file(a) and not file(b)".
To solve this, a new internal "_matchfiles(...)" revset is introduced. It works
like "file(x)" but accepts more than one argument and its arguments are
prefixed with "p:", "i:" and "x:" to be used as patterns, include patterns or
exclude patterns respectively.
The _matchfiles revset is kept private for now:
- There are probably smarter ways to pass the arguments in a user-friendly way
- A "rev:" argument is likely appear at some point to emulate log command
behaviour with regard to filesets: they are evaluated for the parent revision
and applied everywhere instead of being reevaluated for each revision.
author | Patrick Mezard <patrick@mezard.eu> |
---|---|
date | Thu, 23 Feb 2012 18:05:20 +0100 |
parents | 1bfc7ba8b404 |
children | 336e61875335 |
comparison
equal
deleted
inserted
replaced
16160:1bfc7ba8b404 | 16161:5a627b49b4d9 |
---|---|
253 'no_merges': ('not merge()', None), | 253 'no_merges': ('not merge()', None), |
254 'only_merges': ('merge()', None), | 254 'only_merges': ('merge()', None), |
255 'removed': ('removes("*")', None), | 255 'removed': ('removes("*")', None), |
256 'date': ('date(%(val)r)', None), | 256 'date': ('date(%(val)r)', None), |
257 'branch': ('branch(%(val)r)', ' or '), | 257 'branch': ('branch(%(val)r)', ' or '), |
258 'exclude': ('not file(%(val)r)', ' and '), | |
259 'include': ('file(%(val)r)', ' and '), | |
260 '_pats': ('file(%(val)r)', ' or '), | |
261 '_patslog': ('filelog(%(val)r)', ' or '), | 258 '_patslog': ('filelog(%(val)r)', ' or '), |
262 'keyword': ('keyword(%(val)r)', ' or '), | 259 'keyword': ('keyword(%(val)r)', ' or '), |
263 'prune': ('not (%(val)r or ancestors(%(val)r))', ' and '), | 260 'prune': ('not (%(val)r or ancestors(%(val)r))', ' and '), |
264 'user': ('user(%(val)r)', ' or '), | 261 'user': ('user(%(val)r)', ' or '), |
265 'rev': ('%(val)s', ' or '), | 262 'rev': ('%(val)s', ' or '), |
279 if not len(filelog): | 276 if not len(filelog): |
280 # A zero count may be a directory or deleted file, so | 277 # A zero count may be a directory or deleted file, so |
281 # try to find matching entries on the slow path. | 278 # try to find matching entries on the slow path. |
282 slowpath = True | 279 slowpath = True |
283 if slowpath: | 280 if slowpath: |
284 # See cmdutil.walkchangerevs() slow path | 281 # See cmdutil.walkchangerevs() slow path. |
285 opts['_pats'] = list(pats) | 282 # |
283 # pats/include/exclude cannot be represented as separate | |
284 # revset expressions as their filtering logic applies at file | |
285 # level. For instance "-I a -X a" matches a revision touching | |
286 # "a" and "b" while "file(a) and not file(b)" does not. | |
287 matchargs = [] | |
288 for p in pats: | |
289 matchargs.append('p:' + p) | |
290 for p in opts.get('include', []): | |
291 matchargs.append('i:' + p) | |
292 for p in opts.get('exclude', []): | |
293 matchargs.append('x:' + p) | |
294 matchargs = ','.join(('%r' % p) for p in matchargs) | |
295 opts['rev'] = opts.get('rev', []) + ['_matchfiles(%s)' % matchargs] | |
286 else: | 296 else: |
287 opts['_patslog'] = list(pats) | 297 opts['_patslog'] = list(pats) |
288 | 298 |
289 revset = [] | 299 revset = [] |
290 for op, val in opts.iteritems(): | 300 for op, val in opts.iteritems(): |