Mercurial > public > mercurial-scm > hg-stable
diff 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 |
line wrap: on
line diff
--- a/hgext/graphlog.py Thu Feb 23 17:55:07 2012 +0100 +++ b/hgext/graphlog.py Thu Feb 23 18:05:20 2012 +0100 @@ -255,9 +255,6 @@ 'removed': ('removes("*")', None), 'date': ('date(%(val)r)', None), 'branch': ('branch(%(val)r)', ' or '), - 'exclude': ('not file(%(val)r)', ' and '), - 'include': ('file(%(val)r)', ' and '), - '_pats': ('file(%(val)r)', ' or '), '_patslog': ('filelog(%(val)r)', ' or '), 'keyword': ('keyword(%(val)r)', ' or '), 'prune': ('not (%(val)r or ancestors(%(val)r))', ' and '), @@ -281,8 +278,21 @@ # try to find matching entries on the slow path. slowpath = True if slowpath: - # See cmdutil.walkchangerevs() slow path - opts['_pats'] = list(pats) + # See cmdutil.walkchangerevs() slow path. + # + # pats/include/exclude cannot be represented as separate + # revset expressions as their filtering logic applies at file + # level. For instance "-I a -X a" matches a revision touching + # "a" and "b" while "file(a) and not file(b)" does not. + matchargs = [] + for p in pats: + matchargs.append('p:' + p) + for p in opts.get('include', []): + matchargs.append('i:' + p) + for p in opts.get('exclude', []): + matchargs.append('x:' + p) + matchargs = ','.join(('%r' % p) for p in matchargs) + opts['rev'] = opts.get('rev', []) + ['_matchfiles(%s)' % matchargs] else: opts['_patslog'] = list(pats)