120 elif name == root: |
120 elif name == root: |
121 return '' |
121 return '' |
122 else: |
122 else: |
123 raise Abort('%s not under root' % myname) |
123 raise Abort('%s not under root' % myname) |
124 |
124 |
125 def matcher(canonroot, cwd, names, inc, exc, head=''): |
125 def matcher(canonroot, cwd='', names=['.'], inc=[], exc=[], head=''): |
126 """build a function to match a set of file patterns |
126 """build a function to match a set of file patterns |
127 |
127 |
128 arguments: |
128 arguments: |
129 canonroot - the canonical root of the tree you're matching against |
129 canonroot - the canonical root of the tree you're matching against |
130 cwd - the current working directory, if relevant |
130 cwd - the current working directory, if relevant |
132 inc - patterns to include |
132 inc - patterns to include |
133 exc - patterns to exclude |
133 exc - patterns to exclude |
134 head - a regex to prepend to patterns to control whether a match is rooted |
134 head - a regex to prepend to patterns to control whether a match is rooted |
135 |
135 |
136 a pattern is one of: |
136 a pattern is one of: |
137 're:<regex>' |
137 'glob:<rooted glob>' |
138 'glob:<shellglob>' |
138 're:<rooted regexp>' |
139 'path:<explicit path>' |
139 'path:<rooted path>' |
|
140 'relglob:<relative glob>' |
140 'relpath:<relative path>' |
141 'relpath:<relative path>' |
141 '<relative path>' |
142 'relre:<relative regexp>' |
|
143 '<rooted path or regexp>' |
142 |
144 |
143 returns: |
145 returns: |
144 a 3-tuple containing |
146 a 3-tuple containing |
145 - list of explicit non-pattern names passed in |
147 - list of explicit non-pattern names passed in |
146 - a bool match(filename) function |
148 - a bool match(filename) function |
149 todo: |
151 todo: |
150 make head regex a rooted bool |
152 make head regex a rooted bool |
151 """ |
153 """ |
152 |
154 |
153 def patkind(name): |
155 def patkind(name): |
154 for prefix in 're:', 'glob:', 'path:', 'relpath:': |
156 for prefix in 're', 'glob', 'path', 'relglob', 'relpath', 'relre': |
155 if name.startswith(prefix): return name.split(':', 1) |
157 if name.startswith(prefix + ':'): return name.split(':', 1) |
156 for c in name: |
158 for c in name: |
157 if c in _globchars: return 'glob', name |
159 if c in _globchars: return 'glob', name |
158 return 'relpath', name |
160 return 'relpath', name |
159 |
161 |
160 def regex(kind, name, tail): |
162 def regex(kind, name, tail): |
161 '''convert a pattern into a regular expression''' |
163 '''convert a pattern into a regular expression''' |
162 if kind == 're': |
164 if kind == 're': |
163 return name |
165 return name |
164 elif kind == 'path': |
166 elif kind == 'path': |
165 return '^' + re.escape(name) + '(?:/|$)' |
167 return '^' + re.escape(name) + '(?:/|$)' |
|
168 elif kind == 'relglob': |
|
169 return head + globre(name, '(?:|.*/)', tail) |
166 elif kind == 'relpath': |
170 elif kind == 'relpath': |
167 return head + re.escape(name) + tail |
171 return head + re.escape(name) + tail |
|
172 elif kind == 'relre': |
|
173 if name.startswith('^'): |
|
174 return name |
|
175 return '.*' + name |
168 return head + globre(name, '', tail) |
176 return head + globre(name, '', tail) |
169 |
177 |
170 def matchfn(pats, tail): |
178 def matchfn(pats, tail): |
171 """build a matching function from a set of patterns""" |
179 """build a matching function from a set of patterns""" |
172 if pats: |
180 if pats: |