mercurial/match.py
changeset 50695 1c31b343e514
parent 50338 81c7d04f4722
child 51569 b32c3146ec34
equal deleted inserted replaced
50686:a41eeb877d07 50695:1c31b343e514
    28 
    28 
    29 allpatternkinds = (
    29 allpatternkinds = (
    30     b're',
    30     b're',
    31     b'glob',
    31     b'glob',
    32     b'path',
    32     b'path',
       
    33     b'filepath',
    33     b'relglob',
    34     b'relglob',
    34     b'relpath',
    35     b'relpath',
    35     b'relre',
    36     b'relre',
    36     b'rootglob',
    37     b'rootglob',
    37     b'listfile',
    38     b'listfile',
   179     a pattern is one of:
   180     a pattern is one of:
   180     'glob:<glob>' - a glob relative to cwd
   181     'glob:<glob>' - a glob relative to cwd
   181     're:<regexp>' - a regular expression
   182     're:<regexp>' - a regular expression
   182     'path:<path>' - a path relative to repository root, which is matched
   183     'path:<path>' - a path relative to repository root, which is matched
   183                     recursively
   184                     recursively
       
   185     'filepath:<path>' - an exact path to a single file, relative to the
       
   186                         repository root
   184     'rootfilesin:<path>' - a path relative to repository root, which is
   187     'rootfilesin:<path>' - a path relative to repository root, which is
   185                     matched non-recursively (will not match subdirectories)
   188                     matched non-recursively (will not match subdirectories)
   186     'relglob:<glob>' - an unrooted glob (*.c matches C files in all dirs)
   189     'relglob:<glob>' - an unrooted glob (*.c matches C files in all dirs)
   187     'relpath:<path>' - a path relative to cwd
   190     'relpath:<path>' - a path relative to cwd
   188     'relre:<regexp>' - a regexp that needn't match the start of a name
   191     'relre:<regexp>' - a regexp that needn't match the start of a name
   332 
   335 
   333 def _donormalize(patterns, default, root, cwd, auditor=None, warn=None):
   336 def _donormalize(patterns, default, root, cwd, auditor=None, warn=None):
   334     """Convert 'kind:pat' from the patterns list to tuples with kind and
   337     """Convert 'kind:pat' from the patterns list to tuples with kind and
   335     normalized and rooted patterns and with listfiles expanded."""
   338     normalized and rooted patterns and with listfiles expanded."""
   336     kindpats = []
   339     kindpats = []
       
   340     kinds_to_normalize = (
       
   341         b'relglob',
       
   342         b'path',
       
   343         b'filepath',
       
   344         b'rootfilesin',
       
   345         b'rootglob',
       
   346     )
       
   347 
   337     for kind, pat in [_patsplit(p, default) for p in patterns]:
   348     for kind, pat in [_patsplit(p, default) for p in patterns]:
   338         if kind in cwdrelativepatternkinds:
   349         if kind in cwdrelativepatternkinds:
   339             pat = pathutil.canonpath(root, cwd, pat, auditor=auditor)
   350             pat = pathutil.canonpath(root, cwd, pat, auditor=auditor)
   340         elif kind in (b'relglob', b'path', b'rootfilesin', b'rootglob'):
   351         elif kind in kinds_to_normalize:
   341             pat = util.normpath(pat)
   352             pat = util.normpath(pat)
   342         elif kind in (b'listfile', b'listfile0'):
   353         elif kind in (b'listfile', b'listfile0'):
   343             try:
   354             try:
   344                 files = util.readfile(pat)
   355                 files = util.readfile(pat)
   345                 if kind == b'listfile0':
   356                 if kind == b'listfile0':
  1338     globsuffix is appended to the regexp of globs."""
  1349     globsuffix is appended to the regexp of globs."""
  1339     if not pat and kind in (b'glob', b'relpath'):
  1350     if not pat and kind in (b'glob', b'relpath'):
  1340         return b''
  1351         return b''
  1341     if kind == b're':
  1352     if kind == b're':
  1342         return pat
  1353         return pat
       
  1354     if kind == b'filepath':
       
  1355         raise error.ProgrammingError(
       
  1356             "'filepath:' patterns should not be converted to a regex"
       
  1357         )
  1343     if kind in (b'path', b'relpath'):
  1358     if kind in (b'path', b'relpath'):
  1344         if pat == b'.':
  1359         if pat == b'.':
  1345             return b''
  1360             return b''
  1346         return util.stringutil.reescape(pat) + b'(?:/|$)'
  1361         return util.stringutil.reescape(pat) + b'(?:/|$)'
  1347     if kind == b'rootfilesin':
  1362     if kind == b'rootfilesin':
  1442     ...
  1457     ...
  1443     Abort: matcher pattern is too long (20009 bytes)
  1458     Abort: matcher pattern is too long (20009 bytes)
  1444     """
  1459     """
  1445     try:
  1460     try:
  1446         allgroups = []
  1461         allgroups = []
  1447         regexps = [_regex(k, p, globsuffix) for (k, p, s) in kindpats]
  1462         regexps = []
       
  1463         exact = set()
       
  1464         for (kind, pattern, _source) in kindpats:
       
  1465             if kind == b'filepath':
       
  1466                 exact.add(pattern)
       
  1467                 continue
       
  1468             regexps.append(_regex(kind, pattern, globsuffix))
       
  1469 
  1448         fullregexp = _joinregexes(regexps)
  1470         fullregexp = _joinregexes(regexps)
  1449 
  1471 
  1450         startidx = 0
  1472         startidx = 0
  1451         groupsize = 0
  1473         groupsize = 0
  1452         for idx, r in enumerate(regexps):
  1474         for idx, r in enumerate(regexps):
  1467         else:
  1489         else:
  1468             group = regexps[startidx:]
  1490             group = regexps[startidx:]
  1469             allgroups.append(_joinregexes(group))
  1491             allgroups.append(_joinregexes(group))
  1470             allmatchers = [_rematcher(g) for g in allgroups]
  1492             allmatchers = [_rematcher(g) for g in allgroups]
  1471             func = lambda s: any(m(s) for m in allmatchers)
  1493             func = lambda s: any(m(s) for m in allmatchers)
  1472         return fullregexp, func
  1494 
       
  1495         actualfunc = func
       
  1496         if exact:
       
  1497             # An empty regex will always match, so only call the regex if
       
  1498             # there were any actual patterns to match.
       
  1499             if not regexps:
       
  1500                 actualfunc = lambda s: s in exact
       
  1501             else:
       
  1502                 actualfunc = lambda s: s in exact or func(s)
       
  1503         return fullregexp, actualfunc
  1473     except re.error:
  1504     except re.error:
  1474         for k, p, s in kindpats:
  1505         for k, p, s in kindpats:
       
  1506             if k == b'filepath':
       
  1507                 continue
  1475             try:
  1508             try:
  1476                 _rematcher(_regex(k, p, globsuffix))
  1509                 _rematcher(_regex(k, p, globsuffix))
  1477             except re.error:
  1510             except re.error:
  1478                 if s:
  1511                 if s:
  1479                     raise error.Abort(
  1512                     raise error.Abort(
  1500             for p in pat.split(b'/'):
  1533             for p in pat.split(b'/'):
  1501                 if b'[' in p or b'{' in p or b'*' in p or b'?' in p:
  1534                 if b'[' in p or b'{' in p or b'*' in p or b'?' in p:
  1502                     break
  1535                     break
  1503                 root.append(p)
  1536                 root.append(p)
  1504             r.append(b'/'.join(root))
  1537             r.append(b'/'.join(root))
  1505         elif kind in (b'relpath', b'path'):
  1538         elif kind in (b'relpath', b'path', b'filepath'):
  1506             if pat == b'.':
  1539             if pat == b'.':
  1507                 pat = b''
  1540                 pat = b''
  1508             r.append(pat)
  1541             r.append(pat)
  1509         elif kind in (b'rootfilesin',):
  1542         elif kind in (b'rootfilesin',):
  1510             if pat == b'.':
  1543             if pat == b'.':