mercurial/util.py
changeset 824 0932bc2fb2be
parent 814 0902ffece4b4
parent 820 89985a1b3427
child 836 1fe3b14c7044
child 839 9c918287d10b
equal deleted inserted replaced
818:eef752151556 824:0932bc2fb2be
    67     return head + res + tail
    67     return head + res + tail
    68 
    68 
    69 _globchars = {'[': 1, '{': 1, '*': 1, '?': 1}
    69 _globchars = {'[': 1, '{': 1, '*': 1, '?': 1}
    70 
    70 
    71 def matcher(cwd, names, inc, exc, head = ''):
    71 def matcher(cwd, names, inc, exc, head = ''):
    72     def patlike(name):
    72     def patkind(name):
    73         for prefix in 're:', 'glob:', 'path:':
    73         for prefix in 're:', 'glob:', 'path:':
    74             if name.startswith(prefix): return True
    74             if name.startswith(prefix): return name.split(':', 1)
    75         for c in name:
    75         for c in name:
    76             if c in _globchars: return True
    76             if c in _globchars: return 'glob', name
       
    77         return 'relpath', name
       
    78 
       
    79     cwdsep = cwd + os.sep
    77 
    80 
    78     def regex(name, tail):
    81     def regex(name, tail):
    79         '''convert a pattern into a regular expression'''
    82         '''convert a pattern into a regular expression'''
    80         if name.startswith('re:'):
    83         kind, name = patkind(name)
    81             return name[3:]
    84         if kind == 're':
    82         elif name.startswith('path:'):
    85             return name
    83             return '^' + re.escape(name[5:]) + '$'
    86         elif kind == 'path':
    84         elif name.startswith('glob:'):
    87             return '^' + re.escape(name) + '$'
    85             return head + globre(name[5:], '', tail)
    88         if cwd: name = os.path.join(cwdsep, name)
       
    89         name = os.path.normpath(name)
       
    90         if name == '.': name = '**'
    86         return head + globre(name, '', tail)
    91         return head + globre(name, '', tail)
    87 
       
    88     cwdsep = cwd + os.sep
       
    89 
    92 
    90     def under(fn):
    93     def under(fn):
    91         """check if fn is under our cwd"""
    94         """check if fn is under our cwd"""
    92         return not cwd or fn.startswith(cwdsep)
    95         return not cwd or fn.startswith(cwdsep)
    93 
    96 
    94     def matchfn(pats, tail):
    97     def matchfn(pats, tail):
    95         """build a matching function from a set of patterns"""
    98         """build a matching function from a set of patterns"""
    96         if pats:
    99         if pats:
    97             pat = '(?:%s)' % '|'.join([regex(p, tail) for p in pats])
   100             pat = '(?:%s)' % '|'.join([regex(p, tail) for p in pats])
    98             if cwd:
       
    99                 pat = re.escape(cwdsep) + pat
       
   100             return re.compile(pat).match
   101             return re.compile(pat).match
   101 
   102 
   102     pats = filter(patlike, names)
   103     def globprefix(pat):
   103     files = [n for n in names if not patlike(n)]
   104         '''return the non-glob prefix of a path, e.g. foo/* -> foo'''
   104     if pats: plain = []
   105         root = []
   105     elif cwd: plain = [cwdsep + f for f in files]
   106         for p in pat.split(os.sep):
   106     else: plain = files
   107             if patkind(p)[0] == 'glob': break
       
   108             root.append(p)
       
   109         return os.sep.join(root)
       
   110 
       
   111     patkinds = map(patkind, names)
       
   112     pats = [name for (kind, name) in patkinds if kind != 'relpath']
       
   113     files = [name for (kind, name) in patkinds if kind == 'relpath']
       
   114     roots = filter(None, map(globprefix, pats)) + files
       
   115     if cwd: roots = [cwdsep + r for r in roots]
   107         
   116         
   108     patmatch = matchfn(pats, '$')
   117     patmatch = matchfn(pats, '$') or always
   109     filematch = matchfn(files, '(?:/|$)')
   118     filematch = matchfn(files, '(?:/|$)') or always
   110     incmatch = matchfn(inc, '(?:/|$)') or under
   119     incmatch = matchfn(inc, '(?:/|$)') or always
   111     excmatch = matchfn(exc, '(?:/|$)') or (lambda fn: False)
   120     excmatch = matchfn(exc, '(?:/|$)') or (lambda fn: False)
   112 
   121 
   113     return plain, lambda fn: (incmatch(fn) and not excmatch(fn) and
   122     return roots, lambda fn: (incmatch(fn) and not excmatch(fn) and
   114                               (fn.endswith('/') or
   123                               (fn.endswith('/') or
   115                                (not pats and not files) or
   124                                (not pats and not files) or
   116                                (pats and patmatch(fn)) or
   125                                (pats and patmatch(fn)) or
   117                                (files and filematch(fn))))
   126                                (files and filematch(fn))))
   118 
   127