diff mercurial/util.py @ 824:0932bc2fb2be

Merge with BOS
author mpm@selenic.com
date Tue, 02 Aug 2005 08:57:32 -0800
parents 0902ffece4b4 89985a1b3427
children 1fe3b14c7044 9c918287d10b
line wrap: on
line diff
--- a/mercurial/util.py
+++ b/mercurial/util.py
@@ -69,24 +69,27 @@ def globre(pat, head = '^', tail = '$'):
 _globchars = {'[': 1, '{': 1, '*': 1, '?': 1}
 
 def matcher(cwd, names, inc, exc, head = ''):
-    def patlike(name):
+    def patkind(name):
         for prefix in 're:', 'glob:', 'path:':
-            if name.startswith(prefix): return True
+            if name.startswith(prefix): return name.split(':', 1)
         for c in name:
-            if c in _globchars: return True
+            if c in _globchars: return 'glob', name
+        return 'relpath', name
+
+    cwdsep = cwd + os.sep
 
     def regex(name, tail):
         '''convert a pattern into a regular expression'''
-        if name.startswith('re:'):
-            return name[3:]
-        elif name.startswith('path:'):
-            return '^' + re.escape(name[5:]) + '$'
-        elif name.startswith('glob:'):
-            return head + globre(name[5:], '', tail)
+        kind, name = patkind(name)
+        if kind == 're':
+            return name
+        elif kind == 'path':
+            return '^' + re.escape(name) + '$'
+        if cwd: name = os.path.join(cwdsep, name)
+        name = os.path.normpath(name)
+        if name == '.': name = '**'
         return head + globre(name, '', tail)
 
-    cwdsep = cwd + os.sep
-
     def under(fn):
         """check if fn is under our cwd"""
         return not cwd or fn.startswith(cwdsep)
@@ -95,22 +98,28 @@ def matcher(cwd, names, inc, exc, head =
         """build a matching function from a set of patterns"""
         if pats:
             pat = '(?:%s)' % '|'.join([regex(p, tail) for p in pats])
-            if cwd:
-                pat = re.escape(cwdsep) + pat
             return re.compile(pat).match
 
-    pats = filter(patlike, names)
-    files = [n for n in names if not patlike(n)]
-    if pats: plain = []
-    elif cwd: plain = [cwdsep + f for f in files]
-    else: plain = files
+    def globprefix(pat):
+        '''return the non-glob prefix of a path, e.g. foo/* -> foo'''
+        root = []
+        for p in pat.split(os.sep):
+            if patkind(p)[0] == 'glob': break
+            root.append(p)
+        return os.sep.join(root)
+
+    patkinds = map(patkind, names)
+    pats = [name for (kind, name) in patkinds if kind != 'relpath']
+    files = [name for (kind, name) in patkinds if kind == 'relpath']
+    roots = filter(None, map(globprefix, pats)) + files
+    if cwd: roots = [cwdsep + r for r in roots]
         
-    patmatch = matchfn(pats, '$')
-    filematch = matchfn(files, '(?:/|$)')
-    incmatch = matchfn(inc, '(?:/|$)') or under
+    patmatch = matchfn(pats, '$') or always
+    filematch = matchfn(files, '(?:/|$)') or always
+    incmatch = matchfn(inc, '(?:/|$)') or always
     excmatch = matchfn(exc, '(?:/|$)') or (lambda fn: False)
 
-    return plain, lambda fn: (incmatch(fn) and not excmatch(fn) and
+    return roots, lambda fn: (incmatch(fn) and not excmatch(fn) and
                               (fn.endswith('/') or
                                (not pats and not files) or
                                (pats and patmatch(fn)) or