src/mercurialserver/ruleset.py
changeset 237 d30f3f312ece
parent 109 72100d3ed1bd
child 242 03d8f07230b3
--- a/src/mercurialserver/ruleset.py	Tue Dec 15 14:28:45 2009 +0000
+++ b/src/mercurialserver/ruleset.py	Tue Dec 15 15:36:08 2009 +0000
@@ -10,20 +10,24 @@
 import os
 import os.path
 
-allowedchars = "A-Za-z0-9_-"
-
 def globmatcher(pattern):
     p = "[^/]*".join(re.escape(c) for c in pattern.split("*"))
     # ** means "match recursively" ie "ignore directories"
-    rex = re.compile(p.replace("[^/]*[^/]*", ".*") + "$")
-    # None matches everything
-    return lambda x: x is None or rex.match(x) is not None
+    return re.compile(p.replace("[^/]*[^/]*", ".*") + "$")
 
+# Returns True for a definite match
+# False for a definite non-match
+# None where we can't be sure because a key is None
 def rule(pairs):
     matchers = [(k, globmatcher(v)) for k, v in pairs]
     def c(kw):
         for k, m in matchers:
-            if k not in kw or not m(kw[k]):
+            if k not in kw:
+                return False
+            kkw = kw[k]
+            if kkw is None:
+                return None
+            if m.match(kkw) is None:
                 return False
         return True
     return c
@@ -46,32 +50,39 @@
     def get(self, k):
         return self.preset.get(k, None)
         
-    def matchrule(self, kw):
+    def matchrules(self, kw):
         d = self.preset.copy()
         d.update(kw)
+        res = set()
         for a, c in self.rules:
-            if c(d):
-                return a
-        return None
+            m = c(d)
+            if m is None:
+                # "Maybe match" - add it and carry on
+                res.add(a)
+            elif m:
+                # Definite match - add it and stop
+                res.add(a)
+                break
+        return res
 
     def allow(self, level, **kw):
-        a = self.matchrule(kw)
-        return a in self.levels and self.levels.index(a) <= self.levels.index(level)
+        for a in self.matchrules(kw):
+            if a in self.levels:
+                if self.levels.index(a) <= self.levels.index(level):
+                    return True
+        return False
     
     def readfile(self, fn):
+        f = open(fn)
         try:
-            f = open(fn)
-            try:
-                for l in f:
-                    l = l.strip()
-                    if len(l) == 0 or l.startswith("#"):
-                        continue
-                    l = l.split()
-                    self.add(l[0], rule([c.split("=", 1) for c in l[1:]]))
-            finally:
-                f.close()
-        except Exception, e:
-            print >> sys.stderr, "Failure reading rules file:", e
+            for l in f:
+                l = l.strip()
+                if len(l) == 0 or l.startswith("#"):
+                    continue
+                l = l.split()
+                self.add(l[0], rule([c.split("=", 1) for c in l[1:]]))
+        finally:
+            f.close()
 
 rules = Ruleset()