Mercurial > hg
changeset 22513:ca709785caf2
match: simplify brittle predicate construction
In match.__init__(), we create the matchfn predicate by and-ing
together the individual predicates for includes, excludes (negated)
and patterns. Instead of the current set of nested if/else blocks, we
can simplify by adding the predicates to a list and defining the
overall predicate in a generic way based on the components. We can
still optimize it for the 0-length and 1-length cases. This way, there
is no combinatorial explosion to deal with if new component predicates
are added, and there is less risk of getting the overall predicate
wrong.
author | Martin von Zweigbergk <martinvonz@gmail.com> |
---|---|
date | Fri, 19 Sep 2014 13:49:58 -0700 |
parents | 6b6da715cb96 |
children | 48e4e47774bf |
files | mercurial/match.py |
diffstat | 1 files changed, 15 insertions(+), 23 deletions(-) [+] |
line wrap: on
line diff
--- a/mercurial/match.py Tue Sep 23 14:45:23 2014 -0700 +++ b/mercurial/match.py Fri Sep 19 13:49:58 2014 -0700 @@ -66,47 +66,39 @@ self._ctx = ctx self._always = False + matchfns = [] if include: kindpats = _normalize(include, 'glob', root, cwd, auditor) self.includepat, im = _buildmatch(ctx, kindpats, '(?:/|$)') + matchfns.append(im) if exclude: kindpats = _normalize(exclude, 'glob', root, cwd, auditor) self.excludepat, em = _buildmatch(ctx, kindpats, '(?:/|$)') + matchfns.append(lambda f: not em(f)) if exact: if isinstance(patterns, list): self._files = patterns else: self._files = list(patterns) - pm = self.exact + matchfns.append(self.exact) elif patterns: kindpats = _normalize(patterns, default, root, cwd, auditor) self._files = _roots(kindpats) self._anypats = self._anypats or _anypats(kindpats) self.patternspat, pm = _buildmatch(ctx, kindpats, '$') + matchfns.append(pm) - if patterns or exact: - if include: - if exclude: - m = lambda f: im(f) and not em(f) and pm(f) - else: - m = lambda f: im(f) and pm(f) - else: - if exclude: - m = lambda f: not em(f) and pm(f) - else: - m = pm + if not matchfns: + m = util.always + self._always = True + elif len(matchfns) == 1: + m = matchfns[0] else: - if include: - if exclude: - m = lambda f: im(f) and not em(f) - else: - m = im - else: - if exclude: - m = lambda f: not em(f) - else: - m = lambda f: True - self._always = True + def m(f): + for matchfn in matchfns: + if not matchfn(f): + return False + return True self.matchfn = m self._fmap = set(self._files)