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):