src/mercurialserver/ruleset.py
changeset 237 d30f3f312ece
parent 109 72100d3ed1bd
child 242 03d8f07230b3
equal deleted inserted replaced
236:38cea4b518c1 237:d30f3f312ece
     8 import sys
     8 import sys
     9 import re
     9 import re
    10 import os
    10 import os
    11 import os.path
    11 import os.path
    12 
    12 
    13 allowedchars = "A-Za-z0-9_-"
       
    14 
       
    15 def globmatcher(pattern):
    13 def globmatcher(pattern):
    16     p = "[^/]*".join(re.escape(c) for c in pattern.split("*"))
    14     p = "[^/]*".join(re.escape(c) for c in pattern.split("*"))
    17     # ** means "match recursively" ie "ignore directories"
    15     # ** means "match recursively" ie "ignore directories"
    18     rex = re.compile(p.replace("[^/]*[^/]*", ".*") + "$")
    16     return re.compile(p.replace("[^/]*[^/]*", ".*") + "$")
    19     # None matches everything
       
    20     return lambda x: x is None or rex.match(x) is not None
       
    21 
    17 
       
    18 # Returns True for a definite match
       
    19 # False for a definite non-match
       
    20 # None where we can't be sure because a key is None
    22 def rule(pairs):
    21 def rule(pairs):
    23     matchers = [(k, globmatcher(v)) for k, v in pairs]
    22     matchers = [(k, globmatcher(v)) for k, v in pairs]
    24     def c(kw):
    23     def c(kw):
    25         for k, m in matchers:
    24         for k, m in matchers:
    26             if k not in kw or not m(kw[k]):
    25             if k not in kw:
       
    26                 return False
       
    27             kkw = kw[k]
       
    28             if kkw is None:
       
    29                 return None
       
    30             if m.match(kkw) is None:
    27                 return False
    31                 return False
    28         return True
    32         return True
    29     return c
    33     return c
    30 
    34 
    31 class Ruleset(object):
    35 class Ruleset(object):
    44         self.preset.update(kw)
    48         self.preset.update(kw)
    45         
    49         
    46     def get(self, k):
    50     def get(self, k):
    47         return self.preset.get(k, None)
    51         return self.preset.get(k, None)
    48         
    52         
    49     def matchrule(self, kw):
    53     def matchrules(self, kw):
    50         d = self.preset.copy()
    54         d = self.preset.copy()
    51         d.update(kw)
    55         d.update(kw)
       
    56         res = set()
    52         for a, c in self.rules:
    57         for a, c in self.rules:
    53             if c(d):
    58             m = c(d)
    54                 return a
    59             if m is None:
    55         return None
    60                 # "Maybe match" - add it and carry on
       
    61                 res.add(a)
       
    62             elif m:
       
    63                 # Definite match - add it and stop
       
    64                 res.add(a)
       
    65                 break
       
    66         return res
    56 
    67 
    57     def allow(self, level, **kw):
    68     def allow(self, level, **kw):
    58         a = self.matchrule(kw)
    69         for a in self.matchrules(kw):
    59         return a in self.levels and self.levels.index(a) <= self.levels.index(level)
    70             if a in self.levels:
       
    71                 if self.levels.index(a) <= self.levels.index(level):
       
    72                     return True
       
    73         return False
    60     
    74     
    61     def readfile(self, fn):
    75     def readfile(self, fn):
       
    76         f = open(fn)
    62         try:
    77         try:
    63             f = open(fn)
    78             for l in f:
    64             try:
    79                 l = l.strip()
    65                 for l in f:
    80                 if len(l) == 0 or l.startswith("#"):
    66                     l = l.strip()
    81                     continue
    67                     if len(l) == 0 or l.startswith("#"):
    82                 l = l.split()
    68                         continue
    83                 self.add(l[0], rule([c.split("=", 1) for c in l[1:]]))
    69                     l = l.split()
    84         finally:
    70                     self.add(l[0], rule([c.split("=", 1) for c in l[1:]]))
    85             f.close()
    71             finally:
       
    72                 f.close()
       
    73         except Exception, e:
       
    74             print >> sys.stderr, "Failure reading rules file:", e
       
    75 
    86 
    76 rules = Ruleset()
    87 rules = Ruleset()
    77 
    88