diff -r 31d5c6236f71 -r f597eb3b5aaf src/mercurialserver/ruleset.py --- a/src/mercurialserver/ruleset.py Sun Dec 19 09:49:18 2010 +0000 +++ b/src/mercurialserver/ruleset.py Tue Sep 06 11:16:58 2011 +0100 @@ -13,63 +13,56 @@ # ** means "match recursively" ie "ignore directories" 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 +# Returns 1 for a definite match +# -1 for a definite non-match +# 0 where we can't be sure because a key is None +def rmatch(k, m, kw): + if k not in kw: + return -1 + kkw = kw[k] + if kkw is None: + return 0 + elif m.match(kkw) is None: + return -1 + else: + return 1 + 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: - return False - kkw = kw[k] - if kkw is None: - return None - if m.match(kkw) is None: - return False - return True + return min(rmatch(k, m, kw) for k, m in matchers) return c class Ruleset(object): '''Class representing the rules in a rule file''' - + levels = ["init", "write", "read", "deny"] def __init__(self): self.rules = [] self.preset = {} - def add(self, action, conditions): - self.rules.append((action, conditions)) - def set(self, **kw): self.preset.update(kw) - + def get(self, k): return self.preset.get(k, None) - - def matchrules(self, kw): + + def allow(self, level, **kw): + levelindex = self.levels.index(level) d = self.preset.copy() d.update(kw) - res = set() for a, c in self.rules: 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): - for a in self.matchrules(kw): - if a in self.levels: - if self.levels.index(a) <= self.levels.index(level): + if m == 1: + # Definite match - what it says goes + return a <= levelindex + elif m == 0: + # "Maybe match" - allow if it says yes, ignore if no + if a <= levelindex: return True return False - + def readfile(self, fn): f = open(fn) try: @@ -78,9 +71,14 @@ if len(l) == 0 or l.startswith("#"): continue l = l.split() - self.add(l[0], rule([c.split("=", 1) for c in l[1:]])) + # Unrecognized actions are off the high end + if l[0] in self.levels: + ix = self.levels.index(l[0]) + else: + ix = len(self.levels) + self.rules.append((ix, + rule([c.split("=", 1) for c in l[1:]]))) finally: f.close() rules = Ruleset() -