##// END OF EJS Templates
match: fix NameError 'pat' on overflow of regex pattern length...
Yuya Nishihara -
r21191:a2f4ea82 stable
parent child Browse files
Show More
@@ -1,408 +1,408 b''
1 # match.py - filename matching
1 # match.py - filename matching
2 #
2 #
3 # Copyright 2008, 2009 Matt Mackall <mpm@selenic.com> and others
3 # Copyright 2008, 2009 Matt Mackall <mpm@selenic.com> and others
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 import re
8 import re
9 import util, pathutil
9 import util, pathutil
10 from i18n import _
10 from i18n import _
11
11
12 def _rematcher(regex):
12 def _rematcher(regex):
13 '''compile the regexp with the best available regexp engine and return a
13 '''compile the regexp with the best available regexp engine and return a
14 matcher function'''
14 matcher function'''
15 m = util.compilere(regex)
15 m = util.compilere(regex)
16 try:
16 try:
17 # slightly faster, provided by facebook's re2 bindings
17 # slightly faster, provided by facebook's re2 bindings
18 return m.test_match
18 return m.test_match
19 except AttributeError:
19 except AttributeError:
20 return m.match
20 return m.match
21
21
22 def _expandsets(kindpats, ctx):
22 def _expandsets(kindpats, ctx):
23 '''Returns the kindpats list with the 'set' patterns expanded.'''
23 '''Returns the kindpats list with the 'set' patterns expanded.'''
24 fset = set()
24 fset = set()
25 other = []
25 other = []
26
26
27 for kind, pat in kindpats:
27 for kind, pat in kindpats:
28 if kind == 'set':
28 if kind == 'set':
29 if not ctx:
29 if not ctx:
30 raise util.Abort("fileset expression with no context")
30 raise util.Abort("fileset expression with no context")
31 s = ctx.getfileset(pat)
31 s = ctx.getfileset(pat)
32 fset.update(s)
32 fset.update(s)
33 continue
33 continue
34 other.append((kind, pat))
34 other.append((kind, pat))
35 return fset, other
35 return fset, other
36
36
37 class match(object):
37 class match(object):
38 def __init__(self, root, cwd, patterns, include=[], exclude=[],
38 def __init__(self, root, cwd, patterns, include=[], exclude=[],
39 default='glob', exact=False, auditor=None, ctx=None):
39 default='glob', exact=False, auditor=None, ctx=None):
40 """build an object to match a set of file patterns
40 """build an object to match a set of file patterns
41
41
42 arguments:
42 arguments:
43 root - the canonical root of the tree you're matching against
43 root - the canonical root of the tree you're matching against
44 cwd - the current working directory, if relevant
44 cwd - the current working directory, if relevant
45 patterns - patterns to find
45 patterns - patterns to find
46 include - patterns to include (unless they are excluded)
46 include - patterns to include (unless they are excluded)
47 exclude - patterns to exclude (even if they are included)
47 exclude - patterns to exclude (even if they are included)
48 default - if a pattern in patterns has no explicit type, assume this one
48 default - if a pattern in patterns has no explicit type, assume this one
49 exact - patterns are actually filenames (include/exclude still apply)
49 exact - patterns are actually filenames (include/exclude still apply)
50
50
51 a pattern is one of:
51 a pattern is one of:
52 'glob:<glob>' - a glob relative to cwd
52 'glob:<glob>' - a glob relative to cwd
53 're:<regexp>' - a regular expression
53 're:<regexp>' - a regular expression
54 'path:<path>' - a path relative to repository root
54 'path:<path>' - a path relative to repository root
55 'relglob:<glob>' - an unrooted glob (*.c matches C files in all dirs)
55 'relglob:<glob>' - an unrooted glob (*.c matches C files in all dirs)
56 'relpath:<path>' - a path relative to cwd
56 'relpath:<path>' - a path relative to cwd
57 'relre:<regexp>' - a regexp that needn't match the start of a name
57 'relre:<regexp>' - a regexp that needn't match the start of a name
58 'set:<fileset>' - a fileset expression
58 'set:<fileset>' - a fileset expression
59 '<something>' - a pattern of the specified default type
59 '<something>' - a pattern of the specified default type
60 """
60 """
61
61
62 self._root = root
62 self._root = root
63 self._cwd = cwd
63 self._cwd = cwd
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 if include:
69 if include:
70 kindpats = _normalize(include, 'glob', root, cwd, auditor)
70 kindpats = _normalize(include, 'glob', root, cwd, auditor)
71 self.includepat, im = _buildmatch(ctx, kindpats, '(?:/|$)')
71 self.includepat, im = _buildmatch(ctx, kindpats, '(?:/|$)')
72 if exclude:
72 if exclude:
73 kindpats = _normalize(exclude, 'glob', root, cwd, auditor)
73 kindpats = _normalize(exclude, 'glob', root, cwd, auditor)
74 self.excludepat, em = _buildmatch(ctx, kindpats, '(?:/|$)')
74 self.excludepat, em = _buildmatch(ctx, kindpats, '(?:/|$)')
75 if exact:
75 if exact:
76 if isinstance(patterns, list):
76 if isinstance(patterns, list):
77 self._files = patterns
77 self._files = patterns
78 else:
78 else:
79 self._files = list(patterns)
79 self._files = list(patterns)
80 pm = self.exact
80 pm = self.exact
81 elif patterns:
81 elif patterns:
82 kindpats = _normalize(patterns, default, root, cwd, auditor)
82 kindpats = _normalize(patterns, default, root, cwd, auditor)
83 self._files = _roots(kindpats)
83 self._files = _roots(kindpats)
84 self._anypats = self._anypats or _anypats(kindpats)
84 self._anypats = self._anypats or _anypats(kindpats)
85 self.patternspat, pm = _buildmatch(ctx, kindpats, '$')
85 self.patternspat, pm = _buildmatch(ctx, kindpats, '$')
86
86
87 if patterns or exact:
87 if patterns or exact:
88 if include:
88 if include:
89 if exclude:
89 if exclude:
90 m = lambda f: im(f) and not em(f) and pm(f)
90 m = lambda f: im(f) and not em(f) and pm(f)
91 else:
91 else:
92 m = lambda f: im(f) and pm(f)
92 m = lambda f: im(f) and pm(f)
93 else:
93 else:
94 if exclude:
94 if exclude:
95 m = lambda f: not em(f) and pm(f)
95 m = lambda f: not em(f) and pm(f)
96 else:
96 else:
97 m = pm
97 m = pm
98 else:
98 else:
99 if include:
99 if include:
100 if exclude:
100 if exclude:
101 m = lambda f: im(f) and not em(f)
101 m = lambda f: im(f) and not em(f)
102 else:
102 else:
103 m = im
103 m = im
104 else:
104 else:
105 if exclude:
105 if exclude:
106 m = lambda f: not em(f)
106 m = lambda f: not em(f)
107 else:
107 else:
108 m = lambda f: True
108 m = lambda f: True
109 self._always = True
109 self._always = True
110
110
111 self.matchfn = m
111 self.matchfn = m
112 self._fmap = set(self._files)
112 self._fmap = set(self._files)
113
113
114 def __call__(self, fn):
114 def __call__(self, fn):
115 return self.matchfn(fn)
115 return self.matchfn(fn)
116 def __iter__(self):
116 def __iter__(self):
117 for f in self._files:
117 for f in self._files:
118 yield f
118 yield f
119
119
120 # Callbacks related to how the matcher is used by dirstate.walk.
120 # Callbacks related to how the matcher is used by dirstate.walk.
121 # Subscribers to these events must monkeypatch the matcher object.
121 # Subscribers to these events must monkeypatch the matcher object.
122 def bad(self, f, msg):
122 def bad(self, f, msg):
123 '''Callback from dirstate.walk for each explicit file that can't be
123 '''Callback from dirstate.walk for each explicit file that can't be
124 found/accessed, with an error message.'''
124 found/accessed, with an error message.'''
125 pass
125 pass
126
126
127 # If an explicitdir is set, it will be called when an explicitly listed
127 # If an explicitdir is set, it will be called when an explicitly listed
128 # directory is visited.
128 # directory is visited.
129 explicitdir = None
129 explicitdir = None
130
130
131 # If an traversedir is set, it will be called when a directory discovered
131 # If an traversedir is set, it will be called when a directory discovered
132 # by recursive traversal is visited.
132 # by recursive traversal is visited.
133 traversedir = None
133 traversedir = None
134
134
135 def rel(self, f):
135 def rel(self, f):
136 '''Convert repo path back to path that is relative to cwd of matcher.'''
136 '''Convert repo path back to path that is relative to cwd of matcher.'''
137 return util.pathto(self._root, self._cwd, f)
137 return util.pathto(self._root, self._cwd, f)
138
138
139 def files(self):
139 def files(self):
140 '''Explicitly listed files or patterns or roots:
140 '''Explicitly listed files or patterns or roots:
141 if no patterns or .always(): empty list,
141 if no patterns or .always(): empty list,
142 if exact: list exact files,
142 if exact: list exact files,
143 if not .anypats(): list all files and dirs,
143 if not .anypats(): list all files and dirs,
144 else: optimal roots'''
144 else: optimal roots'''
145 return self._files
145 return self._files
146
146
147 def exact(self, f):
147 def exact(self, f):
148 '''Returns True if f is in .files().'''
148 '''Returns True if f is in .files().'''
149 return f in self._fmap
149 return f in self._fmap
150
150
151 def anypats(self):
151 def anypats(self):
152 '''Matcher uses patterns or include/exclude.'''
152 '''Matcher uses patterns or include/exclude.'''
153 return self._anypats
153 return self._anypats
154
154
155 def always(self):
155 def always(self):
156 '''Matcher will match everything and .files() will be empty
156 '''Matcher will match everything and .files() will be empty
157 - optimization might be possible and necessary.'''
157 - optimization might be possible and necessary.'''
158 return self._always
158 return self._always
159
159
160 class exact(match):
160 class exact(match):
161 def __init__(self, root, cwd, files):
161 def __init__(self, root, cwd, files):
162 match.__init__(self, root, cwd, files, exact=True)
162 match.__init__(self, root, cwd, files, exact=True)
163
163
164 class always(match):
164 class always(match):
165 def __init__(self, root, cwd):
165 def __init__(self, root, cwd):
166 match.__init__(self, root, cwd, [])
166 match.__init__(self, root, cwd, [])
167 self._always = True
167 self._always = True
168
168
169 class narrowmatcher(match):
169 class narrowmatcher(match):
170 """Adapt a matcher to work on a subdirectory only.
170 """Adapt a matcher to work on a subdirectory only.
171
171
172 The paths are remapped to remove/insert the path as needed:
172 The paths are remapped to remove/insert the path as needed:
173
173
174 >>> m1 = match('root', '', ['a.txt', 'sub/b.txt'])
174 >>> m1 = match('root', '', ['a.txt', 'sub/b.txt'])
175 >>> m2 = narrowmatcher('sub', m1)
175 >>> m2 = narrowmatcher('sub', m1)
176 >>> bool(m2('a.txt'))
176 >>> bool(m2('a.txt'))
177 False
177 False
178 >>> bool(m2('b.txt'))
178 >>> bool(m2('b.txt'))
179 True
179 True
180 >>> bool(m2.matchfn('a.txt'))
180 >>> bool(m2.matchfn('a.txt'))
181 False
181 False
182 >>> bool(m2.matchfn('b.txt'))
182 >>> bool(m2.matchfn('b.txt'))
183 True
183 True
184 >>> m2.files()
184 >>> m2.files()
185 ['b.txt']
185 ['b.txt']
186 >>> m2.exact('b.txt')
186 >>> m2.exact('b.txt')
187 True
187 True
188 >>> m2.rel('b.txt')
188 >>> m2.rel('b.txt')
189 'b.txt'
189 'b.txt'
190 >>> def bad(f, msg):
190 >>> def bad(f, msg):
191 ... print "%s: %s" % (f, msg)
191 ... print "%s: %s" % (f, msg)
192 >>> m1.bad = bad
192 >>> m1.bad = bad
193 >>> m2.bad('x.txt', 'No such file')
193 >>> m2.bad('x.txt', 'No such file')
194 sub/x.txt: No such file
194 sub/x.txt: No such file
195 """
195 """
196
196
197 def __init__(self, path, matcher):
197 def __init__(self, path, matcher):
198 self._root = matcher._root
198 self._root = matcher._root
199 self._cwd = matcher._cwd
199 self._cwd = matcher._cwd
200 self._path = path
200 self._path = path
201 self._matcher = matcher
201 self._matcher = matcher
202 self._always = matcher._always
202 self._always = matcher._always
203
203
204 self._files = [f[len(path) + 1:] for f in matcher._files
204 self._files = [f[len(path) + 1:] for f in matcher._files
205 if f.startswith(path + "/")]
205 if f.startswith(path + "/")]
206 self._anypats = matcher._anypats
206 self._anypats = matcher._anypats
207 self.matchfn = lambda fn: matcher.matchfn(self._path + "/" + fn)
207 self.matchfn = lambda fn: matcher.matchfn(self._path + "/" + fn)
208 self._fmap = set(self._files)
208 self._fmap = set(self._files)
209
209
210 def bad(self, f, msg):
210 def bad(self, f, msg):
211 self._matcher.bad(self._path + "/" + f, msg)
211 self._matcher.bad(self._path + "/" + f, msg)
212
212
213 def patkind(pattern, default=None):
213 def patkind(pattern, default=None):
214 '''If pattern is 'kind:pat' with a known kind, return kind.'''
214 '''If pattern is 'kind:pat' with a known kind, return kind.'''
215 return _patsplit(pattern, default)[0]
215 return _patsplit(pattern, default)[0]
216
216
217 def _patsplit(pattern, default):
217 def _patsplit(pattern, default):
218 """Split a string into the optional pattern kind prefix and the actual
218 """Split a string into the optional pattern kind prefix and the actual
219 pattern."""
219 pattern."""
220 if ':' in pattern:
220 if ':' in pattern:
221 kind, pat = pattern.split(':', 1)
221 kind, pat = pattern.split(':', 1)
222 if kind in ('re', 'glob', 'path', 'relglob', 'relpath', 'relre',
222 if kind in ('re', 'glob', 'path', 'relglob', 'relpath', 'relre',
223 'listfile', 'listfile0', 'set'):
223 'listfile', 'listfile0', 'set'):
224 return kind, pat
224 return kind, pat
225 return default, pattern
225 return default, pattern
226
226
227 def _globre(pat):
227 def _globre(pat):
228 r'''Convert an extended glob string to a regexp string.
228 r'''Convert an extended glob string to a regexp string.
229
229
230 >>> print _globre(r'?')
230 >>> print _globre(r'?')
231 .
231 .
232 >>> print _globre(r'*')
232 >>> print _globre(r'*')
233 [^/]*
233 [^/]*
234 >>> print _globre(r'**')
234 >>> print _globre(r'**')
235 .*
235 .*
236 >>> print _globre(r'[a*?!^][^b][!c]')
236 >>> print _globre(r'[a*?!^][^b][!c]')
237 [a*?!^][\^b][^c]
237 [a*?!^][\^b][^c]
238 >>> print _globre(r'{a,b}')
238 >>> print _globre(r'{a,b}')
239 (?:a|b)
239 (?:a|b)
240 >>> print _globre(r'.\*\?')
240 >>> print _globre(r'.\*\?')
241 \.\*\?
241 \.\*\?
242 '''
242 '''
243 i, n = 0, len(pat)
243 i, n = 0, len(pat)
244 res = ''
244 res = ''
245 group = 0
245 group = 0
246 escape = re.escape
246 escape = re.escape
247 def peek():
247 def peek():
248 return i < n and pat[i]
248 return i < n and pat[i]
249 while i < n:
249 while i < n:
250 c = pat[i]
250 c = pat[i]
251 i += 1
251 i += 1
252 if c not in '*?[{},\\':
252 if c not in '*?[{},\\':
253 res += escape(c)
253 res += escape(c)
254 elif c == '*':
254 elif c == '*':
255 if peek() == '*':
255 if peek() == '*':
256 i += 1
256 i += 1
257 res += '.*'
257 res += '.*'
258 else:
258 else:
259 res += '[^/]*'
259 res += '[^/]*'
260 elif c == '?':
260 elif c == '?':
261 res += '.'
261 res += '.'
262 elif c == '[':
262 elif c == '[':
263 j = i
263 j = i
264 if j < n and pat[j] in '!]':
264 if j < n and pat[j] in '!]':
265 j += 1
265 j += 1
266 while j < n and pat[j] != ']':
266 while j < n and pat[j] != ']':
267 j += 1
267 j += 1
268 if j >= n:
268 if j >= n:
269 res += '\\['
269 res += '\\['
270 else:
270 else:
271 stuff = pat[i:j].replace('\\','\\\\')
271 stuff = pat[i:j].replace('\\','\\\\')
272 i = j + 1
272 i = j + 1
273 if stuff[0] == '!':
273 if stuff[0] == '!':
274 stuff = '^' + stuff[1:]
274 stuff = '^' + stuff[1:]
275 elif stuff[0] == '^':
275 elif stuff[0] == '^':
276 stuff = '\\' + stuff
276 stuff = '\\' + stuff
277 res = '%s[%s]' % (res, stuff)
277 res = '%s[%s]' % (res, stuff)
278 elif c == '{':
278 elif c == '{':
279 group += 1
279 group += 1
280 res += '(?:'
280 res += '(?:'
281 elif c == '}' and group:
281 elif c == '}' and group:
282 res += ')'
282 res += ')'
283 group -= 1
283 group -= 1
284 elif c == ',' and group:
284 elif c == ',' and group:
285 res += '|'
285 res += '|'
286 elif c == '\\':
286 elif c == '\\':
287 p = peek()
287 p = peek()
288 if p:
288 if p:
289 i += 1
289 i += 1
290 res += escape(p)
290 res += escape(p)
291 else:
291 else:
292 res += escape(c)
292 res += escape(c)
293 else:
293 else:
294 res += escape(c)
294 res += escape(c)
295 return res
295 return res
296
296
297 def _regex(kind, pat, globsuffix):
297 def _regex(kind, pat, globsuffix):
298 '''Convert a (normalized) pattern of any kind into a regular expression.
298 '''Convert a (normalized) pattern of any kind into a regular expression.
299 globsuffix is appended to the regexp of globs.'''
299 globsuffix is appended to the regexp of globs.'''
300 if not pat:
300 if not pat:
301 return ''
301 return ''
302 if kind == 're':
302 if kind == 're':
303 return pat
303 return pat
304 if kind == 'path':
304 if kind == 'path':
305 return '^' + re.escape(pat) + '(?:/|$)'
305 return '^' + re.escape(pat) + '(?:/|$)'
306 if kind == 'relglob':
306 if kind == 'relglob':
307 return '(?:|.*/)' + _globre(pat) + globsuffix
307 return '(?:|.*/)' + _globre(pat) + globsuffix
308 if kind == 'relpath':
308 if kind == 'relpath':
309 return re.escape(pat) + '(?:/|$)'
309 return re.escape(pat) + '(?:/|$)'
310 if kind == 'relre':
310 if kind == 'relre':
311 if pat.startswith('^'):
311 if pat.startswith('^'):
312 return pat
312 return pat
313 return '.*' + pat
313 return '.*' + pat
314 return _globre(pat) + globsuffix
314 return _globre(pat) + globsuffix
315
315
316 def _buildmatch(ctx, kindpats, globsuffix):
316 def _buildmatch(ctx, kindpats, globsuffix):
317 '''Return regexp string and a matcher function for kindpats.
317 '''Return regexp string and a matcher function for kindpats.
318 globsuffix is appended to the regexp of globs.'''
318 globsuffix is appended to the regexp of globs.'''
319 fset, kindpats = _expandsets(kindpats, ctx)
319 fset, kindpats = _expandsets(kindpats, ctx)
320 if not kindpats:
320 if not kindpats:
321 return "", fset.__contains__
321 return "", fset.__contains__
322
322
323 regex, mf = _buildregexmatch(kindpats, globsuffix)
323 regex, mf = _buildregexmatch(kindpats, globsuffix)
324 if fset:
324 if fset:
325 return regex, lambda f: f in fset or mf(f)
325 return regex, lambda f: f in fset or mf(f)
326 return regex, mf
326 return regex, mf
327
327
328 def _buildregexmatch(kindpats, globsuffix):
328 def _buildregexmatch(kindpats, globsuffix):
329 """Build a match function from a list of kinds and kindpats,
329 """Build a match function from a list of kinds and kindpats,
330 return regexp string and a matcher function."""
330 return regexp string and a matcher function."""
331 try:
331 try:
332 regex = '(?:%s)' % '|'.join([_regex(k, p, globsuffix)
332 regex = '(?:%s)' % '|'.join([_regex(k, p, globsuffix)
333 for (k, p) in kindpats])
333 for (k, p) in kindpats])
334 if len(regex) > 20000:
334 if len(regex) > 20000:
335 raise OverflowError
335 raise OverflowError
336 return regex, _rematcher(regex)
336 return regex, _rematcher(regex)
337 except OverflowError:
337 except OverflowError:
338 # We're using a Python with a tiny regex engine and we
338 # We're using a Python with a tiny regex engine and we
339 # made it explode, so we'll divide the pattern list in two
339 # made it explode, so we'll divide the pattern list in two
340 # until it works
340 # until it works
341 l = len(kindpats)
341 l = len(kindpats)
342 if l < 2:
342 if l < 2:
343 raise
343 raise
344 regexa, a = _buildregexmatch(kindpats[:l//2], globsuffix)
344 regexa, a = _buildregexmatch(kindpats[:l//2], globsuffix)
345 regexb, b = _buildregexmatch(kindpats[l//2:], globsuffix)
345 regexb, b = _buildregexmatch(kindpats[l//2:], globsuffix)
346 return pat, lambda s: a(s) or b(s)
346 return regex, lambda s: a(s) or b(s)
347 except re.error:
347 except re.error:
348 for k, p in kindpats:
348 for k, p in kindpats:
349 try:
349 try:
350 _rematcher('(?:%s)' % _regex(k, p, globsuffix))
350 _rematcher('(?:%s)' % _regex(k, p, globsuffix))
351 except re.error:
351 except re.error:
352 raise util.Abort(_("invalid pattern (%s): %s") % (k, p))
352 raise util.Abort(_("invalid pattern (%s): %s") % (k, p))
353 raise util.Abort(_("invalid pattern"))
353 raise util.Abort(_("invalid pattern"))
354
354
355 def _normalize(patterns, default, root, cwd, auditor):
355 def _normalize(patterns, default, root, cwd, auditor):
356 '''Convert 'kind:pat' from the patterns list to tuples with kind and
356 '''Convert 'kind:pat' from the patterns list to tuples with kind and
357 normalized and rooted patterns and with listfiles expanded.'''
357 normalized and rooted patterns and with listfiles expanded.'''
358 kindpats = []
358 kindpats = []
359 for kind, pat in [_patsplit(p, default) for p in patterns]:
359 for kind, pat in [_patsplit(p, default) for p in patterns]:
360 if kind in ('glob', 'relpath'):
360 if kind in ('glob', 'relpath'):
361 pat = pathutil.canonpath(root, cwd, pat, auditor)
361 pat = pathutil.canonpath(root, cwd, pat, auditor)
362 elif kind in ('relglob', 'path'):
362 elif kind in ('relglob', 'path'):
363 pat = util.normpath(pat)
363 pat = util.normpath(pat)
364 elif kind in ('listfile', 'listfile0'):
364 elif kind in ('listfile', 'listfile0'):
365 try:
365 try:
366 files = util.readfile(pat)
366 files = util.readfile(pat)
367 if kind == 'listfile0':
367 if kind == 'listfile0':
368 files = files.split('\0')
368 files = files.split('\0')
369 else:
369 else:
370 files = files.splitlines()
370 files = files.splitlines()
371 files = [f for f in files if f]
371 files = [f for f in files if f]
372 except EnvironmentError:
372 except EnvironmentError:
373 raise util.Abort(_("unable to read file list (%s)") % pat)
373 raise util.Abort(_("unable to read file list (%s)") % pat)
374 kindpats += _normalize(files, default, root, cwd, auditor)
374 kindpats += _normalize(files, default, root, cwd, auditor)
375 continue
375 continue
376 # else: re or relre - which cannot be normalized
376 # else: re or relre - which cannot be normalized
377 kindpats.append((kind, pat))
377 kindpats.append((kind, pat))
378 return kindpats
378 return kindpats
379
379
380 def _roots(kindpats):
380 def _roots(kindpats):
381 '''return roots and exact explicitly listed files from patterns
381 '''return roots and exact explicitly listed files from patterns
382
382
383 >>> _roots([('glob', 'g/*'), ('glob', 'g'), ('glob', 'g*')])
383 >>> _roots([('glob', 'g/*'), ('glob', 'g'), ('glob', 'g*')])
384 ['g', 'g', '.']
384 ['g', 'g', '.']
385 >>> _roots([('relpath', 'r'), ('path', 'p/p'), ('path', '')])
385 >>> _roots([('relpath', 'r'), ('path', 'p/p'), ('path', '')])
386 ['r', 'p/p', '.']
386 ['r', 'p/p', '.']
387 >>> _roots([('relglob', 'rg*'), ('re', 're/'), ('relre', 'rr')])
387 >>> _roots([('relglob', 'rg*'), ('re', 're/'), ('relre', 'rr')])
388 ['.', '.', '.']
388 ['.', '.', '.']
389 '''
389 '''
390 r = []
390 r = []
391 for kind, pat in kindpats:
391 for kind, pat in kindpats:
392 if kind == 'glob': # find the non-glob prefix
392 if kind == 'glob': # find the non-glob prefix
393 root = []
393 root = []
394 for p in pat.split('/'):
394 for p in pat.split('/'):
395 if '[' in p or '{' in p or '*' in p or '?' in p:
395 if '[' in p or '{' in p or '*' in p or '?' in p:
396 break
396 break
397 root.append(p)
397 root.append(p)
398 r.append('/'.join(root) or '.')
398 r.append('/'.join(root) or '.')
399 elif kind in ('relpath', 'path'):
399 elif kind in ('relpath', 'path'):
400 r.append(pat or '.')
400 r.append(pat or '.')
401 else: # relglob, re, relre
401 else: # relglob, re, relre
402 r.append('.')
402 r.append('.')
403 return r
403 return r
404
404
405 def _anypats(kindpats):
405 def _anypats(kindpats):
406 for kind, pat in kindpats:
406 for kind, pat in kindpats:
407 if kind in ('glob', 're', 'relglob', 'relre', 'set'):
407 if kind in ('glob', 're', 'relglob', 'relre', 'set'):
408 return True
408 return True
@@ -1,333 +1,344 b''
1 $ hg init t
1 $ hg init t
2 $ cd t
2 $ cd t
3 $ mkdir -p beans
3 $ mkdir -p beans
4 $ for b in kidney navy turtle borlotti black pinto; do
4 $ for b in kidney navy turtle borlotti black pinto; do
5 > echo $b > beans/$b
5 > echo $b > beans/$b
6 > done
6 > done
7 $ mkdir -p mammals/Procyonidae
7 $ mkdir -p mammals/Procyonidae
8 $ for m in cacomistle coatimundi raccoon; do
8 $ for m in cacomistle coatimundi raccoon; do
9 > echo $m > mammals/Procyonidae/$m
9 > echo $m > mammals/Procyonidae/$m
10 > done
10 > done
11 $ echo skunk > mammals/skunk
11 $ echo skunk > mammals/skunk
12 $ echo fennel > fennel
12 $ echo fennel > fennel
13 $ echo fenugreek > fenugreek
13 $ echo fenugreek > fenugreek
14 $ echo fiddlehead > fiddlehead
14 $ echo fiddlehead > fiddlehead
15 $ hg addremove
15 $ hg addremove
16 adding beans/black
16 adding beans/black
17 adding beans/borlotti
17 adding beans/borlotti
18 adding beans/kidney
18 adding beans/kidney
19 adding beans/navy
19 adding beans/navy
20 adding beans/pinto
20 adding beans/pinto
21 adding beans/turtle
21 adding beans/turtle
22 adding fennel
22 adding fennel
23 adding fenugreek
23 adding fenugreek
24 adding fiddlehead
24 adding fiddlehead
25 adding mammals/Procyonidae/cacomistle
25 adding mammals/Procyonidae/cacomistle
26 adding mammals/Procyonidae/coatimundi
26 adding mammals/Procyonidae/coatimundi
27 adding mammals/Procyonidae/raccoon
27 adding mammals/Procyonidae/raccoon
28 adding mammals/skunk
28 adding mammals/skunk
29 $ hg commit -m "commit #0"
29 $ hg commit -m "commit #0"
30
30
31 $ hg debugwalk
31 $ hg debugwalk
32 f beans/black beans/black
32 f beans/black beans/black
33 f beans/borlotti beans/borlotti
33 f beans/borlotti beans/borlotti
34 f beans/kidney beans/kidney
34 f beans/kidney beans/kidney
35 f beans/navy beans/navy
35 f beans/navy beans/navy
36 f beans/pinto beans/pinto
36 f beans/pinto beans/pinto
37 f beans/turtle beans/turtle
37 f beans/turtle beans/turtle
38 f fennel fennel
38 f fennel fennel
39 f fenugreek fenugreek
39 f fenugreek fenugreek
40 f fiddlehead fiddlehead
40 f fiddlehead fiddlehead
41 f mammals/Procyonidae/cacomistle mammals/Procyonidae/cacomistle
41 f mammals/Procyonidae/cacomistle mammals/Procyonidae/cacomistle
42 f mammals/Procyonidae/coatimundi mammals/Procyonidae/coatimundi
42 f mammals/Procyonidae/coatimundi mammals/Procyonidae/coatimundi
43 f mammals/Procyonidae/raccoon mammals/Procyonidae/raccoon
43 f mammals/Procyonidae/raccoon mammals/Procyonidae/raccoon
44 f mammals/skunk mammals/skunk
44 f mammals/skunk mammals/skunk
45 $ hg debugwalk -I.
45 $ hg debugwalk -I.
46 f beans/black beans/black
46 f beans/black beans/black
47 f beans/borlotti beans/borlotti
47 f beans/borlotti beans/borlotti
48 f beans/kidney beans/kidney
48 f beans/kidney beans/kidney
49 f beans/navy beans/navy
49 f beans/navy beans/navy
50 f beans/pinto beans/pinto
50 f beans/pinto beans/pinto
51 f beans/turtle beans/turtle
51 f beans/turtle beans/turtle
52 f fennel fennel
52 f fennel fennel
53 f fenugreek fenugreek
53 f fenugreek fenugreek
54 f fiddlehead fiddlehead
54 f fiddlehead fiddlehead
55 f mammals/Procyonidae/cacomistle mammals/Procyonidae/cacomistle
55 f mammals/Procyonidae/cacomistle mammals/Procyonidae/cacomistle
56 f mammals/Procyonidae/coatimundi mammals/Procyonidae/coatimundi
56 f mammals/Procyonidae/coatimundi mammals/Procyonidae/coatimundi
57 f mammals/Procyonidae/raccoon mammals/Procyonidae/raccoon
57 f mammals/Procyonidae/raccoon mammals/Procyonidae/raccoon
58 f mammals/skunk mammals/skunk
58 f mammals/skunk mammals/skunk
59
59
60 $ cd mammals
60 $ cd mammals
61 $ hg debugwalk
61 $ hg debugwalk
62 f beans/black ../beans/black
62 f beans/black ../beans/black
63 f beans/borlotti ../beans/borlotti
63 f beans/borlotti ../beans/borlotti
64 f beans/kidney ../beans/kidney
64 f beans/kidney ../beans/kidney
65 f beans/navy ../beans/navy
65 f beans/navy ../beans/navy
66 f beans/pinto ../beans/pinto
66 f beans/pinto ../beans/pinto
67 f beans/turtle ../beans/turtle
67 f beans/turtle ../beans/turtle
68 f fennel ../fennel
68 f fennel ../fennel
69 f fenugreek ../fenugreek
69 f fenugreek ../fenugreek
70 f fiddlehead ../fiddlehead
70 f fiddlehead ../fiddlehead
71 f mammals/Procyonidae/cacomistle Procyonidae/cacomistle
71 f mammals/Procyonidae/cacomistle Procyonidae/cacomistle
72 f mammals/Procyonidae/coatimundi Procyonidae/coatimundi
72 f mammals/Procyonidae/coatimundi Procyonidae/coatimundi
73 f mammals/Procyonidae/raccoon Procyonidae/raccoon
73 f mammals/Procyonidae/raccoon Procyonidae/raccoon
74 f mammals/skunk skunk
74 f mammals/skunk skunk
75 $ hg debugwalk -X ../beans
75 $ hg debugwalk -X ../beans
76 f fennel ../fennel
76 f fennel ../fennel
77 f fenugreek ../fenugreek
77 f fenugreek ../fenugreek
78 f fiddlehead ../fiddlehead
78 f fiddlehead ../fiddlehead
79 f mammals/Procyonidae/cacomistle Procyonidae/cacomistle
79 f mammals/Procyonidae/cacomistle Procyonidae/cacomistle
80 f mammals/Procyonidae/coatimundi Procyonidae/coatimundi
80 f mammals/Procyonidae/coatimundi Procyonidae/coatimundi
81 f mammals/Procyonidae/raccoon Procyonidae/raccoon
81 f mammals/Procyonidae/raccoon Procyonidae/raccoon
82 f mammals/skunk skunk
82 f mammals/skunk skunk
83 $ hg debugwalk -I '*k'
83 $ hg debugwalk -I '*k'
84 f mammals/skunk skunk
84 f mammals/skunk skunk
85 $ hg debugwalk -I 'glob:*k'
85 $ hg debugwalk -I 'glob:*k'
86 f mammals/skunk skunk
86 f mammals/skunk skunk
87 $ hg debugwalk -I 'relglob:*k'
87 $ hg debugwalk -I 'relglob:*k'
88 f beans/black ../beans/black
88 f beans/black ../beans/black
89 f fenugreek ../fenugreek
89 f fenugreek ../fenugreek
90 f mammals/skunk skunk
90 f mammals/skunk skunk
91 $ hg debugwalk -I 'relglob:*k' .
91 $ hg debugwalk -I 'relglob:*k' .
92 f mammals/skunk skunk
92 f mammals/skunk skunk
93 $ hg debugwalk -I 're:.*k$'
93 $ hg debugwalk -I 're:.*k$'
94 f beans/black ../beans/black
94 f beans/black ../beans/black
95 f fenugreek ../fenugreek
95 f fenugreek ../fenugreek
96 f mammals/skunk skunk
96 f mammals/skunk skunk
97 $ hg debugwalk -I 'relre:.*k$'
97 $ hg debugwalk -I 'relre:.*k$'
98 f beans/black ../beans/black
98 f beans/black ../beans/black
99 f fenugreek ../fenugreek
99 f fenugreek ../fenugreek
100 f mammals/skunk skunk
100 f mammals/skunk skunk
101 $ hg debugwalk -I 'path:beans'
101 $ hg debugwalk -I 'path:beans'
102 f beans/black ../beans/black
102 f beans/black ../beans/black
103 f beans/borlotti ../beans/borlotti
103 f beans/borlotti ../beans/borlotti
104 f beans/kidney ../beans/kidney
104 f beans/kidney ../beans/kidney
105 f beans/navy ../beans/navy
105 f beans/navy ../beans/navy
106 f beans/pinto ../beans/pinto
106 f beans/pinto ../beans/pinto
107 f beans/turtle ../beans/turtle
107 f beans/turtle ../beans/turtle
108 $ hg debugwalk -I 'relpath:detour/../../beans'
108 $ hg debugwalk -I 'relpath:detour/../../beans'
109 f beans/black ../beans/black
109 f beans/black ../beans/black
110 f beans/borlotti ../beans/borlotti
110 f beans/borlotti ../beans/borlotti
111 f beans/kidney ../beans/kidney
111 f beans/kidney ../beans/kidney
112 f beans/navy ../beans/navy
112 f beans/navy ../beans/navy
113 f beans/pinto ../beans/pinto
113 f beans/pinto ../beans/pinto
114 f beans/turtle ../beans/turtle
114 f beans/turtle ../beans/turtle
115 $ hg debugwalk .
115 $ hg debugwalk .
116 f mammals/Procyonidae/cacomistle Procyonidae/cacomistle
116 f mammals/Procyonidae/cacomistle Procyonidae/cacomistle
117 f mammals/Procyonidae/coatimundi Procyonidae/coatimundi
117 f mammals/Procyonidae/coatimundi Procyonidae/coatimundi
118 f mammals/Procyonidae/raccoon Procyonidae/raccoon
118 f mammals/Procyonidae/raccoon Procyonidae/raccoon
119 f mammals/skunk skunk
119 f mammals/skunk skunk
120 $ hg debugwalk -I.
120 $ hg debugwalk -I.
121 f mammals/Procyonidae/cacomistle Procyonidae/cacomistle
121 f mammals/Procyonidae/cacomistle Procyonidae/cacomistle
122 f mammals/Procyonidae/coatimundi Procyonidae/coatimundi
122 f mammals/Procyonidae/coatimundi Procyonidae/coatimundi
123 f mammals/Procyonidae/raccoon Procyonidae/raccoon
123 f mammals/Procyonidae/raccoon Procyonidae/raccoon
124 f mammals/skunk skunk
124 f mammals/skunk skunk
125 $ hg debugwalk Procyonidae
125 $ hg debugwalk Procyonidae
126 f mammals/Procyonidae/cacomistle Procyonidae/cacomistle
126 f mammals/Procyonidae/cacomistle Procyonidae/cacomistle
127 f mammals/Procyonidae/coatimundi Procyonidae/coatimundi
127 f mammals/Procyonidae/coatimundi Procyonidae/coatimundi
128 f mammals/Procyonidae/raccoon Procyonidae/raccoon
128 f mammals/Procyonidae/raccoon Procyonidae/raccoon
129
129
130 $ cd Procyonidae
130 $ cd Procyonidae
131 $ hg debugwalk .
131 $ hg debugwalk .
132 f mammals/Procyonidae/cacomistle cacomistle
132 f mammals/Procyonidae/cacomistle cacomistle
133 f mammals/Procyonidae/coatimundi coatimundi
133 f mammals/Procyonidae/coatimundi coatimundi
134 f mammals/Procyonidae/raccoon raccoon
134 f mammals/Procyonidae/raccoon raccoon
135 $ hg debugwalk ..
135 $ hg debugwalk ..
136 f mammals/Procyonidae/cacomistle cacomistle
136 f mammals/Procyonidae/cacomistle cacomistle
137 f mammals/Procyonidae/coatimundi coatimundi
137 f mammals/Procyonidae/coatimundi coatimundi
138 f mammals/Procyonidae/raccoon raccoon
138 f mammals/Procyonidae/raccoon raccoon
139 f mammals/skunk ../skunk
139 f mammals/skunk ../skunk
140 $ cd ..
140 $ cd ..
141
141
142 $ hg debugwalk ../beans
142 $ hg debugwalk ../beans
143 f beans/black ../beans/black
143 f beans/black ../beans/black
144 f beans/borlotti ../beans/borlotti
144 f beans/borlotti ../beans/borlotti
145 f beans/kidney ../beans/kidney
145 f beans/kidney ../beans/kidney
146 f beans/navy ../beans/navy
146 f beans/navy ../beans/navy
147 f beans/pinto ../beans/pinto
147 f beans/pinto ../beans/pinto
148 f beans/turtle ../beans/turtle
148 f beans/turtle ../beans/turtle
149 $ hg debugwalk .
149 $ hg debugwalk .
150 f mammals/Procyonidae/cacomistle Procyonidae/cacomistle
150 f mammals/Procyonidae/cacomistle Procyonidae/cacomistle
151 f mammals/Procyonidae/coatimundi Procyonidae/coatimundi
151 f mammals/Procyonidae/coatimundi Procyonidae/coatimundi
152 f mammals/Procyonidae/raccoon Procyonidae/raccoon
152 f mammals/Procyonidae/raccoon Procyonidae/raccoon
153 f mammals/skunk skunk
153 f mammals/skunk skunk
154 $ hg debugwalk .hg
154 $ hg debugwalk .hg
155 abort: path 'mammals/.hg' is inside nested repo 'mammals' (glob)
155 abort: path 'mammals/.hg' is inside nested repo 'mammals' (glob)
156 [255]
156 [255]
157 $ hg debugwalk ../.hg
157 $ hg debugwalk ../.hg
158 abort: path contains illegal component: .hg
158 abort: path contains illegal component: .hg
159 [255]
159 [255]
160 $ cd ..
160 $ cd ..
161
161
162 $ hg debugwalk -Ibeans
162 $ hg debugwalk -Ibeans
163 f beans/black beans/black
163 f beans/black beans/black
164 f beans/borlotti beans/borlotti
164 f beans/borlotti beans/borlotti
165 f beans/kidney beans/kidney
165 f beans/kidney beans/kidney
166 f beans/navy beans/navy
166 f beans/navy beans/navy
167 f beans/pinto beans/pinto
167 f beans/pinto beans/pinto
168 f beans/turtle beans/turtle
168 f beans/turtle beans/turtle
169 $ hg debugwalk -I '{*,{b,m}*/*}k'
169 $ hg debugwalk -I '{*,{b,m}*/*}k'
170 f beans/black beans/black
170 f beans/black beans/black
171 f fenugreek fenugreek
171 f fenugreek fenugreek
172 f mammals/skunk mammals/skunk
172 f mammals/skunk mammals/skunk
173 $ hg debugwalk 'glob:mammals/../beans/b*'
173 $ hg debugwalk 'glob:mammals/../beans/b*'
174 f beans/black beans/black
174 f beans/black beans/black
175 f beans/borlotti beans/borlotti
175 f beans/borlotti beans/borlotti
176 $ hg debugwalk '-X*/Procyonidae' mammals
176 $ hg debugwalk '-X*/Procyonidae' mammals
177 f mammals/skunk mammals/skunk
177 f mammals/skunk mammals/skunk
178 $ hg debugwalk path:mammals
178 $ hg debugwalk path:mammals
179 f mammals/Procyonidae/cacomistle mammals/Procyonidae/cacomistle
179 f mammals/Procyonidae/cacomistle mammals/Procyonidae/cacomistle
180 f mammals/Procyonidae/coatimundi mammals/Procyonidae/coatimundi
180 f mammals/Procyonidae/coatimundi mammals/Procyonidae/coatimundi
181 f mammals/Procyonidae/raccoon mammals/Procyonidae/raccoon
181 f mammals/Procyonidae/raccoon mammals/Procyonidae/raccoon
182 f mammals/skunk mammals/skunk
182 f mammals/skunk mammals/skunk
183 $ hg debugwalk ..
183 $ hg debugwalk ..
184 abort: .. not under root '$TESTTMP/t' (glob)
184 abort: .. not under root '$TESTTMP/t' (glob)
185 [255]
185 [255]
186 $ hg debugwalk beans/../..
186 $ hg debugwalk beans/../..
187 abort: beans/../.. not under root '$TESTTMP/t' (glob)
187 abort: beans/../.. not under root '$TESTTMP/t' (glob)
188 [255]
188 [255]
189 $ hg debugwalk .hg
189 $ hg debugwalk .hg
190 abort: path contains illegal component: .hg
190 abort: path contains illegal component: .hg
191 [255]
191 [255]
192 $ hg debugwalk beans/../.hg
192 $ hg debugwalk beans/../.hg
193 abort: path contains illegal component: .hg
193 abort: path contains illegal component: .hg
194 [255]
194 [255]
195 $ hg debugwalk beans/../.hg/data
195 $ hg debugwalk beans/../.hg/data
196 abort: path contains illegal component: .hg/data (glob)
196 abort: path contains illegal component: .hg/data (glob)
197 [255]
197 [255]
198 $ hg debugwalk beans/.hg
198 $ hg debugwalk beans/.hg
199 abort: path 'beans/.hg' is inside nested repo 'beans' (glob)
199 abort: path 'beans/.hg' is inside nested repo 'beans' (glob)
200 [255]
200 [255]
201
201
202 Test absolute paths:
202 Test absolute paths:
203
203
204 $ hg debugwalk `pwd`/beans
204 $ hg debugwalk `pwd`/beans
205 f beans/black beans/black
205 f beans/black beans/black
206 f beans/borlotti beans/borlotti
206 f beans/borlotti beans/borlotti
207 f beans/kidney beans/kidney
207 f beans/kidney beans/kidney
208 f beans/navy beans/navy
208 f beans/navy beans/navy
209 f beans/pinto beans/pinto
209 f beans/pinto beans/pinto
210 f beans/turtle beans/turtle
210 f beans/turtle beans/turtle
211 $ hg debugwalk `pwd`/..
211 $ hg debugwalk `pwd`/..
212 abort: $TESTTMP/t/.. not under root '$TESTTMP/t' (glob)
212 abort: $TESTTMP/t/.. not under root '$TESTTMP/t' (glob)
213 [255]
213 [255]
214
214
215 Test patterns:
215 Test patterns:
216
216
217 $ hg debugwalk glob:\*
217 $ hg debugwalk glob:\*
218 f fennel fennel
218 f fennel fennel
219 f fenugreek fenugreek
219 f fenugreek fenugreek
220 f fiddlehead fiddlehead
220 f fiddlehead fiddlehead
221 #if eol-in-paths
221 #if eol-in-paths
222 $ echo glob:glob > glob:glob
222 $ echo glob:glob > glob:glob
223 $ hg addremove
223 $ hg addremove
224 adding glob:glob
224 adding glob:glob
225 warning: filename contains ':', which is reserved on Windows: 'glob:glob'
225 warning: filename contains ':', which is reserved on Windows: 'glob:glob'
226 $ hg debugwalk glob:\*
226 $ hg debugwalk glob:\*
227 f fennel fennel
227 f fennel fennel
228 f fenugreek fenugreek
228 f fenugreek fenugreek
229 f fiddlehead fiddlehead
229 f fiddlehead fiddlehead
230 f glob:glob glob:glob
230 f glob:glob glob:glob
231 $ hg debugwalk glob:glob
231 $ hg debugwalk glob:glob
232 glob: No such file or directory
232 glob: No such file or directory
233 $ hg debugwalk glob:glob:glob
233 $ hg debugwalk glob:glob:glob
234 f glob:glob glob:glob exact
234 f glob:glob glob:glob exact
235 $ hg debugwalk path:glob:glob
235 $ hg debugwalk path:glob:glob
236 f glob:glob glob:glob exact
236 f glob:glob glob:glob exact
237 $ rm glob:glob
237 $ rm glob:glob
238 $ hg addremove
238 $ hg addremove
239 removing glob:glob
239 removing glob:glob
240 #endif
240 #endif
241
241
242 $ hg debugwalk 'glob:**e'
242 $ hg debugwalk 'glob:**e'
243 f beans/turtle beans/turtle
243 f beans/turtle beans/turtle
244 f mammals/Procyonidae/cacomistle mammals/Procyonidae/cacomistle
244 f mammals/Procyonidae/cacomistle mammals/Procyonidae/cacomistle
245
245
246 $ hg debugwalk 're:.*[kb]$'
246 $ hg debugwalk 're:.*[kb]$'
247 f beans/black beans/black
247 f beans/black beans/black
248 f fenugreek fenugreek
248 f fenugreek fenugreek
249 f mammals/skunk mammals/skunk
249 f mammals/skunk mammals/skunk
250
250
251 $ hg debugwalk path:beans/black
251 $ hg debugwalk path:beans/black
252 f beans/black beans/black exact
252 f beans/black beans/black exact
253 $ hg debugwalk path:beans//black
253 $ hg debugwalk path:beans//black
254 f beans/black beans/black exact
254 f beans/black beans/black exact
255
255
256 $ hg debugwalk relglob:Procyonidae
256 $ hg debugwalk relglob:Procyonidae
257 $ hg debugwalk 'relglob:Procyonidae/**'
257 $ hg debugwalk 'relglob:Procyonidae/**'
258 f mammals/Procyonidae/cacomistle mammals/Procyonidae/cacomistle
258 f mammals/Procyonidae/cacomistle mammals/Procyonidae/cacomistle
259 f mammals/Procyonidae/coatimundi mammals/Procyonidae/coatimundi
259 f mammals/Procyonidae/coatimundi mammals/Procyonidae/coatimundi
260 f mammals/Procyonidae/raccoon mammals/Procyonidae/raccoon
260 f mammals/Procyonidae/raccoon mammals/Procyonidae/raccoon
261 $ hg debugwalk 'relglob:Procyonidae/**' fennel
261 $ hg debugwalk 'relglob:Procyonidae/**' fennel
262 f fennel fennel exact
262 f fennel fennel exact
263 f mammals/Procyonidae/cacomistle mammals/Procyonidae/cacomistle
263 f mammals/Procyonidae/cacomistle mammals/Procyonidae/cacomistle
264 f mammals/Procyonidae/coatimundi mammals/Procyonidae/coatimundi
264 f mammals/Procyonidae/coatimundi mammals/Procyonidae/coatimundi
265 f mammals/Procyonidae/raccoon mammals/Procyonidae/raccoon
265 f mammals/Procyonidae/raccoon mammals/Procyonidae/raccoon
266 $ hg debugwalk beans 'glob:beans/*'
266 $ hg debugwalk beans 'glob:beans/*'
267 f beans/black beans/black
267 f beans/black beans/black
268 f beans/borlotti beans/borlotti
268 f beans/borlotti beans/borlotti
269 f beans/kidney beans/kidney
269 f beans/kidney beans/kidney
270 f beans/navy beans/navy
270 f beans/navy beans/navy
271 f beans/pinto beans/pinto
271 f beans/pinto beans/pinto
272 f beans/turtle beans/turtle
272 f beans/turtle beans/turtle
273 $ hg debugwalk 'glob:mamm**'
273 $ hg debugwalk 'glob:mamm**'
274 f mammals/Procyonidae/cacomistle mammals/Procyonidae/cacomistle
274 f mammals/Procyonidae/cacomistle mammals/Procyonidae/cacomistle
275 f mammals/Procyonidae/coatimundi mammals/Procyonidae/coatimundi
275 f mammals/Procyonidae/coatimundi mammals/Procyonidae/coatimundi
276 f mammals/Procyonidae/raccoon mammals/Procyonidae/raccoon
276 f mammals/Procyonidae/raccoon mammals/Procyonidae/raccoon
277 f mammals/skunk mammals/skunk
277 f mammals/skunk mammals/skunk
278 $ hg debugwalk 'glob:mamm**' fennel
278 $ hg debugwalk 'glob:mamm**' fennel
279 f fennel fennel exact
279 f fennel fennel exact
280 f mammals/Procyonidae/cacomistle mammals/Procyonidae/cacomistle
280 f mammals/Procyonidae/cacomistle mammals/Procyonidae/cacomistle
281 f mammals/Procyonidae/coatimundi mammals/Procyonidae/coatimundi
281 f mammals/Procyonidae/coatimundi mammals/Procyonidae/coatimundi
282 f mammals/Procyonidae/raccoon mammals/Procyonidae/raccoon
282 f mammals/Procyonidae/raccoon mammals/Procyonidae/raccoon
283 f mammals/skunk mammals/skunk
283 f mammals/skunk mammals/skunk
284 $ hg debugwalk 'glob:j*'
284 $ hg debugwalk 'glob:j*'
285 $ hg debugwalk NOEXIST
285 $ hg debugwalk NOEXIST
286 NOEXIST: * (glob)
286 NOEXIST: * (glob)
287
287
288 #if fifo
288 #if fifo
289 $ mkfifo fifo
289 $ mkfifo fifo
290 $ hg debugwalk fifo
290 $ hg debugwalk fifo
291 fifo: unsupported file type (type is fifo)
291 fifo: unsupported file type (type is fifo)
292 #endif
292 #endif
293
293
294 $ rm fenugreek
294 $ rm fenugreek
295 $ hg debugwalk fenugreek
295 $ hg debugwalk fenugreek
296 f fenugreek fenugreek exact
296 f fenugreek fenugreek exact
297 $ hg rm fenugreek
297 $ hg rm fenugreek
298 $ hg debugwalk fenugreek
298 $ hg debugwalk fenugreek
299 f fenugreek fenugreek exact
299 f fenugreek fenugreek exact
300 $ touch new
300 $ touch new
301 $ hg debugwalk new
301 $ hg debugwalk new
302 f new new exact
302 f new new exact
303
303
304 $ mkdir ignored
304 $ mkdir ignored
305 $ touch ignored/file
305 $ touch ignored/file
306 $ echo '^ignored$' > .hgignore
306 $ echo '^ignored$' > .hgignore
307 $ hg debugwalk ignored
307 $ hg debugwalk ignored
308 $ hg debugwalk ignored/file
308 $ hg debugwalk ignored/file
309 f ignored/file ignored/file exact
309 f ignored/file ignored/file exact
310
310
311 Test listfile and listfile0
311 Test listfile and listfile0
312
312
313 $ python -c "file('listfile0', 'wb').write('fenugreek\0new\0')"
313 $ python -c "file('listfile0', 'wb').write('fenugreek\0new\0')"
314 $ hg debugwalk -I 'listfile0:listfile0'
314 $ hg debugwalk -I 'listfile0:listfile0'
315 f fenugreek fenugreek
315 f fenugreek fenugreek
316 f new new
316 f new new
317 $ python -c "file('listfile', 'wb').write('fenugreek\nnew\r\nmammals/skunk\n')"
317 $ python -c "file('listfile', 'wb').write('fenugreek\nnew\r\nmammals/skunk\n')"
318 $ hg debugwalk -I 'listfile:listfile'
318 $ hg debugwalk -I 'listfile:listfile'
319 f fenugreek fenugreek
319 f fenugreek fenugreek
320 f mammals/skunk mammals/skunk
320 f mammals/skunk mammals/skunk
321 f new new
321 f new new
322
322
323 $ cd ..
323 $ cd ..
324 $ hg debugwalk -R t t/mammals/skunk
324 $ hg debugwalk -R t t/mammals/skunk
325 f mammals/skunk t/mammals/skunk exact
325 f mammals/skunk t/mammals/skunk exact
326 $ mkdir t2
326 $ mkdir t2
327 $ cd t2
327 $ cd t2
328 $ hg debugwalk -R ../t ../t/mammals/skunk
328 $ hg debugwalk -R ../t ../t/mammals/skunk
329 f mammals/skunk ../t/mammals/skunk exact
329 f mammals/skunk ../t/mammals/skunk exact
330 $ hg debugwalk --cwd ../t mammals/skunk
330 $ hg debugwalk --cwd ../t mammals/skunk
331 f mammals/skunk mammals/skunk exact
331 f mammals/skunk mammals/skunk exact
332
332
333 $ cd ..
333 $ cd ..
334
335 Test split patterns on overflow
336
337 $ cd t
338 $ echo fennel > overflow.list
339 $ python -c "for i in xrange(20000 / 100): print 'x' * 100" >> overflow.list
340 $ echo fenugreek >> overflow.list
341 $ hg debugwalk 'listfile:overflow.list' 2>&1 | grep -v '^xxx'
342 f fennel fennel exact
343 f fenugreek fenugreek exact
344 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now