access.py
author Paul Crowley <paul@ciphergoth.org>
Tue, 22 Apr 2008 10:13:39 +0100
changeset 20 f4daa224dc7e
parent 18 538d6b198f4a
child 21 59540181a4bb
permissions -rw-r--r--
Add support for locking by branch, and document breaking in.

# Copyright 2008 LShift Ltd
# Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com>
#
# Authors:
# Paul Crowley <paul@lshift.net>
# Vadim Gelfer <vadim.gelfer@gmail.com>
#
# This software may be used and distributed according to the terms
# of the GNU General Public License, incorporated herein by reference.

from mercurial.i18n import _
from mercurial.node import *
from mercurial import util

import os
import rules

class Checker(object):
    '''acl checker.'''

    def __init__(self, ui, repo):
        self.ui = ui
        self.repo = repo
        self.repo_path = os.environ['HG_REPO_PATH']
        self.user = os.environ['REMOTE_USER']
        self.rules = rules.Ruleset.readfile(os.environ['HG_ACCESS_RULES_FILE'])

    def allow(self, node):
        '''return if access allowed, raise exception if not.'''
        ctx = self.repo.changectx(node)
        branch = ctx.branch()
        if not self.rules.allow("write", user=self.user, repo=self.repo_path, branch=self.branch, file=None):
            self.ui.debug(_('%s: user %s not allowed on branch %s\n') %
                (__name__, self.user, branch))
            return False
        for f in ctx.files():
            if not self.rules.allow("write", user=self.user, repo=self.repo_path, branch=self.branch, file=f):
                self.ui.debug(_('%s: user %s not allowed on %s\n') %
                              (__name__, self.user, f))
                return False
        self.ui.debug(_('%s: allowing changeset %s\n') % (__name__, short(node)))
        return True

    def check(self, node):
        if not allow(self, node):
            raise util.Abort(_('%s: access denied for changeset %s') %
                (__name__, short(node)))

        
def hook(ui, repo, hooktype, node=None, source=None, **kwargs):
    if hooktype != 'pretxnchangegroup':
        raise util.Abort(_('config error - hook type "%s" cannot stop '
                           'incoming changesets') % hooktype)
    c = Checker(ui, repo)
    start = repo.changelog.rev(bin(node))
    end = repo.changelog.count()
    for rev in xrange(start, end):
        c.check(repo.changelog.node(rev))