Mercurial > hg
comparison mercurial/match.py @ 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 | d516b6de3821 |
children | bbb2f8b0459e |
comparison
equal
deleted
inserted
replaced
22512:6b6da715cb96 | 22513:ca709785caf2 |
---|---|
64 self._files = [] # exact files and roots of patterns | 64 self._files = [] # exact files and roots of patterns |
65 self._anypats = bool(include or exclude) | 65 self._anypats = bool(include or exclude) |
66 self._ctx = ctx | 66 self._ctx = ctx |
67 self._always = False | 67 self._always = False |
68 | 68 |
69 matchfns = [] | |
69 if include: | 70 if include: |
70 kindpats = _normalize(include, 'glob', root, cwd, auditor) | 71 kindpats = _normalize(include, 'glob', root, cwd, auditor) |
71 self.includepat, im = _buildmatch(ctx, kindpats, '(?:/|$)') | 72 self.includepat, im = _buildmatch(ctx, kindpats, '(?:/|$)') |
73 matchfns.append(im) | |
72 if exclude: | 74 if exclude: |
73 kindpats = _normalize(exclude, 'glob', root, cwd, auditor) | 75 kindpats = _normalize(exclude, 'glob', root, cwd, auditor) |
74 self.excludepat, em = _buildmatch(ctx, kindpats, '(?:/|$)') | 76 self.excludepat, em = _buildmatch(ctx, kindpats, '(?:/|$)') |
77 matchfns.append(lambda f: not em(f)) | |
75 if exact: | 78 if exact: |
76 if isinstance(patterns, list): | 79 if isinstance(patterns, list): |
77 self._files = patterns | 80 self._files = patterns |
78 else: | 81 else: |
79 self._files = list(patterns) | 82 self._files = list(patterns) |
80 pm = self.exact | 83 matchfns.append(self.exact) |
81 elif patterns: | 84 elif patterns: |
82 kindpats = _normalize(patterns, default, root, cwd, auditor) | 85 kindpats = _normalize(patterns, default, root, cwd, auditor) |
83 self._files = _roots(kindpats) | 86 self._files = _roots(kindpats) |
84 self._anypats = self._anypats or _anypats(kindpats) | 87 self._anypats = self._anypats or _anypats(kindpats) |
85 self.patternspat, pm = _buildmatch(ctx, kindpats, '$') | 88 self.patternspat, pm = _buildmatch(ctx, kindpats, '$') |
86 | 89 matchfns.append(pm) |
87 if patterns or exact: | 90 |
88 if include: | 91 if not matchfns: |
89 if exclude: | 92 m = util.always |
90 m = lambda f: im(f) and not em(f) and pm(f) | 93 self._always = True |
91 else: | 94 elif len(matchfns) == 1: |
92 m = lambda f: im(f) and pm(f) | 95 m = matchfns[0] |
93 else: | |
94 if exclude: | |
95 m = lambda f: not em(f) and pm(f) | |
96 else: | |
97 m = pm | |
98 else: | 96 else: |
99 if include: | 97 def m(f): |
100 if exclude: | 98 for matchfn in matchfns: |
101 m = lambda f: im(f) and not em(f) | 99 if not matchfn(f): |
102 else: | 100 return False |
103 m = im | 101 return True |
104 else: | |
105 if exclude: | |
106 m = lambda f: not em(f) | |
107 else: | |
108 m = lambda f: True | |
109 self._always = True | |
110 | 102 |
111 self.matchfn = m | 103 self.matchfn = m |
112 self._fmap = set(self._files) | 104 self._fmap = set(self._files) |
113 | 105 |
114 def __call__(self, fn): | 106 def __call__(self, fn): |