# HG changeset patch # User Matt Mackall # Date 2011-06-18 21:53:44 # Node ID cfc89398f710af8015754faceae6d0abf093ad8a # Parent 1c151b963254a41f7775180ac50cf999666841eb match: introduce basic fileset support diff --git a/mercurial/match.py b/mercurial/match.py --- a/mercurial/match.py +++ b/mercurial/match.py @@ -6,9 +6,24 @@ # GNU General Public License version 2 or any later version. import re -import scmutil, util +import scmutil, util, fileset from i18n import _ +def _expandsets(pats, ctx): + '''convert set: patterns into a list of files in the given context''' + fset = set() + other = [] + + for kind, expr in pats: + if kind == 'set': + if not ctx: + raise util.Abort("fileset expression with no context") + s = fileset.getfileset(ctx, expr) + fset.update(s) + continue + other.append((kind, expr)) + return fset, other + class match(object): def __init__(self, root, cwd, patterns, include=[], exclude=[], default='glob', exact=False, auditor=None, ctx=None): @@ -30,9 +45,11 @@ class match(object): 'relglob:' - an unrooted glob (*.c matches C files in all dirs) 'relpath:' - a path relative to cwd 'relre:' - a regexp that needn't match the start of a name + 'set:' - a fileset expression '' - a pattern of the specified default type """ + self._ctx = None self._root = root self._cwd = cwd self._files = [] @@ -41,10 +58,10 @@ class match(object): if include: pats = _normalize(include, 'glob', root, cwd, auditor) - self.includepat, im = _buildmatch(pats, '(?:/|$)') + self.includepat, im = _buildmatch(ctx, pats, '(?:/|$)') if exclude: pats = _normalize(exclude, 'glob', root, cwd, auditor) - self.excludepat, em = _buildmatch(pats, '(?:/|$)') + self.excludepat, em = _buildmatch(ctx, pats, '(?:/|$)') if exact: self._files = patterns pm = self.exact @@ -52,7 +69,7 @@ class match(object): pats = _normalize(patterns, default, root, cwd, auditor) self._files = _roots(pats) self._anypats = self._anypats or _anypats(pats) - self.patternspat, pm = _buildmatch(pats, '$') + self.patternspat, pm = _buildmatch(ctx, pats, '$') if patterns or exact: if include: @@ -163,7 +180,7 @@ def _patsplit(pat, default): if ':' in pat: kind, val = pat.split(':', 1) if kind in ('re', 'glob', 'path', 'relglob', 'relpath', 'relre', - 'listfile', 'listfile0'): + 'listfile', 'listfile0', 'set'): return kind, val return default, pat @@ -241,7 +258,17 @@ def _regex(kind, name, tail): return '.*' + name return _globre(name) + tail -def _buildmatch(pats, tail): +def _buildmatch(ctx, pats, tail): + fset, pats = _expandsets(pats, ctx) + if not pats: + return "", fset.__contains__ + + pat, mf = _buildregexmatch(pats, tail) + if fset: + return pat, lambda f: f in fset or mf(f) + return pat, mf + +def _buildregexmatch(pats, tail): """build a matching function from a set of patterns""" try: pat = '(?:%s)' % '|'.join([_regex(k, p, tail) for (k, p) in pats])