Mercurial > hg
comparison mercurial/match.py @ 25213:08a8e9da0ae7
match: add source to kindpats list
Future patches will be adding the ability to recursively include pattern files
in a match rule expression. Part of that behavior will require tracking which
file each pattern came from so we can report errors correctly.
Let's add a 'source' arg to the kindpats list to track this. Initially it will
only be populated by listfile rules.
author | Durham Goode <durham@fb.com> |
---|---|
date | Sat, 16 May 2015 15:51:03 -0700 |
parents | 472a685a4961 |
children | 08703b10c3ae |
comparison
equal
deleted
inserted
replaced
25212:a39c35e8e559 | 25213:08a8e9da0ae7 |
---|---|
24 def _expandsets(kindpats, ctx, listsubrepos): | 24 def _expandsets(kindpats, ctx, listsubrepos): |
25 '''Returns the kindpats list with the 'set' patterns expanded.''' | 25 '''Returns the kindpats list with the 'set' patterns expanded.''' |
26 fset = set() | 26 fset = set() |
27 other = [] | 27 other = [] |
28 | 28 |
29 for kind, pat in kindpats: | 29 for kind, pat, source in kindpats: |
30 if kind == 'set': | 30 if kind == 'set': |
31 if not ctx: | 31 if not ctx: |
32 raise util.Abort("fileset expression with no context") | 32 raise util.Abort("fileset expression with no context") |
33 s = ctx.getfileset(pat) | 33 s = ctx.getfileset(pat) |
34 fset.update(s) | 34 fset.update(s) |
37 for subpath in ctx.substate: | 37 for subpath in ctx.substate: |
38 s = ctx.sub(subpath).getfileset(pat) | 38 s = ctx.sub(subpath).getfileset(pat) |
39 fset.update(subpath + '/' + f for f in s) | 39 fset.update(subpath + '/' + f for f in s) |
40 | 40 |
41 continue | 41 continue |
42 other.append((kind, pat)) | 42 other.append((kind, pat, source)) |
43 return fset, other | 43 return fset, other |
44 | 44 |
45 def _kindpatsalwaysmatch(kindpats): | 45 def _kindpatsalwaysmatch(kindpats): |
46 """"Checks whether the kindspats match everything, as e.g. | 46 """"Checks whether the kindspats match everything, as e.g. |
47 'relpath:.' does. | 47 'relpath:.' does. |
48 """ | 48 """ |
49 for kind, pat in kindpats: | 49 for kind, pat, source in kindpats: |
50 if pat != '' or kind not in ['relpath', 'glob']: | 50 if pat != '' or kind not in ['relpath', 'glob']: |
51 return False | 51 return False |
52 return True | 52 return True |
53 | 53 |
54 class match(object): | 54 class match(object): |
220 else: | 220 else: |
221 files = files.splitlines() | 221 files = files.splitlines() |
222 files = [f for f in files if f] | 222 files = [f for f in files if f] |
223 except EnvironmentError: | 223 except EnvironmentError: |
224 raise util.Abort(_("unable to read file list (%s)") % pat) | 224 raise util.Abort(_("unable to read file list (%s)") % pat) |
225 kindpats += self._normalize(files, default, root, cwd, auditor) | 225 for k, p, source in self._normalize(files, default, root, cwd, |
226 auditor): | |
227 kindpats.append((k, p, pat)) | |
226 continue | 228 continue |
227 # else: re or relre - which cannot be normalized | 229 # else: re or relre - which cannot be normalized |
228 kindpats.append((kind, pat)) | 230 kindpats.append((kind, pat, '')) |
229 return kindpats | 231 return kindpats |
230 | 232 |
231 def exact(root, cwd, files): | 233 def exact(root, cwd, files): |
232 return match(root, cwd, files, exact=True) | 234 return match(root, cwd, files, exact=True) |
233 | 235 |
313 | 315 |
314 def _normalize(self, patterns, default, root, cwd, auditor): | 316 def _normalize(self, patterns, default, root, cwd, auditor): |
315 self._kp = super(icasefsmatcher, self)._normalize(patterns, default, | 317 self._kp = super(icasefsmatcher, self)._normalize(patterns, default, |
316 root, cwd, auditor) | 318 root, cwd, auditor) |
317 kindpats = [] | 319 kindpats = [] |
318 for kind, pats in self._kp: | 320 for kind, pats, source in self._kp: |
319 if kind not in ('re', 'relre'): # regex can't be normalized | 321 if kind not in ('re', 'relre'): # regex can't be normalized |
320 pats = self._dsnormalize(pats) | 322 pats = self._dsnormalize(pats) |
321 kindpats.append((kind, pats)) | 323 kindpats.append((kind, pats, source)) |
322 return kindpats | 324 return kindpats |
323 | 325 |
324 def patkind(pattern, default=None): | 326 def patkind(pattern, default=None): |
325 '''If pattern is 'kind:pat' with a known kind, return kind.''' | 327 '''If pattern is 'kind:pat' with a known kind, return kind.''' |
326 return _patsplit(pattern, default)[0] | 328 return _patsplit(pattern, default)[0] |
447 def _buildregexmatch(kindpats, globsuffix): | 449 def _buildregexmatch(kindpats, globsuffix): |
448 """Build a match function from a list of kinds and kindpats, | 450 """Build a match function from a list of kinds and kindpats, |
449 return regexp string and a matcher function.""" | 451 return regexp string and a matcher function.""" |
450 try: | 452 try: |
451 regex = '(?:%s)' % '|'.join([_regex(k, p, globsuffix) | 453 regex = '(?:%s)' % '|'.join([_regex(k, p, globsuffix) |
452 for (k, p) in kindpats]) | 454 for (k, p, s) in kindpats]) |
453 if len(regex) > 20000: | 455 if len(regex) > 20000: |
454 raise OverflowError | 456 raise OverflowError |
455 return regex, _rematcher(regex) | 457 return regex, _rematcher(regex) |
456 except OverflowError: | 458 except OverflowError: |
457 # We're using a Python with a tiny regex engine and we | 459 # We're using a Python with a tiny regex engine and we |
462 raise | 464 raise |
463 regexa, a = _buildregexmatch(kindpats[:l//2], globsuffix) | 465 regexa, a = _buildregexmatch(kindpats[:l//2], globsuffix) |
464 regexb, b = _buildregexmatch(kindpats[l//2:], globsuffix) | 466 regexb, b = _buildregexmatch(kindpats[l//2:], globsuffix) |
465 return regex, lambda s: a(s) or b(s) | 467 return regex, lambda s: a(s) or b(s) |
466 except re.error: | 468 except re.error: |
467 for k, p in kindpats: | 469 for k, p, s in kindpats: |
468 try: | 470 try: |
469 _rematcher('(?:%s)' % _regex(k, p, globsuffix)) | 471 _rematcher('(?:%s)' % _regex(k, p, globsuffix)) |
470 except re.error: | 472 except re.error: |
471 raise util.Abort(_("invalid pattern (%s): %s") % (k, p)) | 473 if s: |
474 raise util.Abort(_("%s: invalid pattern (%s): %s") % | |
475 (s, k, p)) | |
476 else: | |
477 raise util.Abort(_("invalid pattern (%s): %s") % (k, p)) | |
472 raise util.Abort(_("invalid pattern")) | 478 raise util.Abort(_("invalid pattern")) |
473 | 479 |
474 def _roots(kindpats): | 480 def _roots(kindpats): |
475 '''return roots and exact explicitly listed files from patterns | 481 '''return roots and exact explicitly listed files from patterns |
476 | 482 |
477 >>> _roots([('glob', 'g/*'), ('glob', 'g'), ('glob', 'g*')]) | 483 >>> _roots([('glob', 'g/*', ''), ('glob', 'g', ''), ('glob', 'g*', '')]) |
478 ['g', 'g', '.'] | 484 ['g', 'g', '.'] |
479 >>> _roots([('relpath', 'r'), ('path', 'p/p'), ('path', '')]) | 485 >>> _roots([('relpath', 'r', ''), ('path', 'p/p', ''), ('path', '', '')]) |
480 ['r', 'p/p', '.'] | 486 ['r', 'p/p', '.'] |
481 >>> _roots([('relglob', 'rg*'), ('re', 're/'), ('relre', 'rr')]) | 487 >>> _roots([('relglob', 'rg*', ''), ('re', 're/', ''), ('relre', 'rr', '')]) |
482 ['.', '.', '.'] | 488 ['.', '.', '.'] |
483 ''' | 489 ''' |
484 r = [] | 490 r = [] |
485 for kind, pat in kindpats: | 491 for kind, pat, source in kindpats: |
486 if kind == 'glob': # find the non-glob prefix | 492 if kind == 'glob': # find the non-glob prefix |
487 root = [] | 493 root = [] |
488 for p in pat.split('/'): | 494 for p in pat.split('/'): |
489 if '[' in p or '{' in p or '*' in p or '?' in p: | 495 if '[' in p or '{' in p or '*' in p or '?' in p: |
490 break | 496 break |
495 else: # relglob, re, relre | 501 else: # relglob, re, relre |
496 r.append('.') | 502 r.append('.') |
497 return r | 503 return r |
498 | 504 |
499 def _anypats(kindpats): | 505 def _anypats(kindpats): |
500 for kind, pat in kindpats: | 506 for kind, pat, source in kindpats: |
501 if kind in ('glob', 're', 'relglob', 'relre', 'set'): | 507 if kind in ('glob', 're', 'relglob', 'relre', 'set'): |
502 return True | 508 return True |
503 | 509 |
504 _commentre = None | 510 _commentre = None |
505 | 511 |