[PATCH - BACL] Branch access control extension

Elifarley Callado Coelho Cruz elifarley at gmail.com
Mon Apr 12 15:22:44 CDT 2010


The BACL hook makes it possible to allow or deny write access to named
branches of a repository when receiving incoming changesets.

This functionality is found on Subversion, so users migrating from it
may find it useful.


Example configuration:

[bacl]
sources = serve
# check if source of incoming changes in this list
# ("serve" == ssh or http, "push", "pull", "bundle")

[bacl.allow]
#branch-a = user-1, user-2, user-3
#branch-b = user-1
#* = super-user
#branch-for-tests = *

[bacl.deny]
#frozen-branch = *
#* = bad-user


---------------------------------------

# HG changeset patch
# User Elifarley Callado Coelho Cruz <elifarley at gmail.com>
# Date 1271103110 10800
# Node ID 7d74df0a1c99e824def8e4ebd003bd0175a8ee50
# Parent  bbf496db07668450aa342186eebde13cebd86e4c
Created bacl - branch access control for mercurial.

diff --git a/hgext/bacl.py b/hgext/bacl.py
new file mode 100644
--- /dev/null
+++ b/hgext/bacl.py
@@ -0,0 +1,82 @@
+# bacl.py - branch access control for mercurial
+#
+# Copyright 2010 Elifarley Cruz <elifarley at gmail.com>
+# Based on acl.py by Vadim Gelfer <vadim.gelfer at gmail.com>
+
+# This software may be used and distributed according to the terms of the
+# GNU General Public License version 2 or any later version.
+
+'''hooks for controlling branch access
+
+This hook makes it possible to allow or deny write access to named branches
+of a repository when receiving incoming changesets.
+
+Example configuration:
+
+[bacl]
+sources = serve
+# check if source of incoming changes in this list
+# ("serve" == ssh or http, "push", "pull", "bundle")
+
+[bacl.allow]
+#branch-a = user-1, user-2, user-3
+#branch-b = user-1
+#* = super-user
+#branch-for-tests = *
+
+[bacl.deny]
+#frozen-branch = *
+#* = bad-user
+
+'''
+
+from mercurial.i18n import _
+from mercurial import util, match
+import getpass, urllib
+
+def buildmatch(ui, user, key):
+    '''return tuple of (match function, list enabled).'''
+    if not ui.has_section(key):
+        ui.debug('bacl: "%s" not enabled\n' % key)
+        return None
+
+    branches = [branch for branch, users in ui.configitems(key)
+            if users == '*' or user in users.replace(',', ' ').split()]
+    ui.debug('bacl: "%s" enabled, %d entries for user "%s"\n' %
+             (key, len(branches), user))
+    if branches:
+        return lambda b: '*' in branches or b in branches
+    return lambda b: False
+
+def hook(ui, repo, hooktype, node=None, source=None, **kwargs):
+    if hooktype not in ['pretxnchangegroup', 'pretxncommit']:
+        raise util.Abort(_('config error - hook type "%s" cannot stop '
+                           'incoming changesets nor commits') % hooktype)
+    if 'pretxnchangegroup' == hooktype and source not in
ui.config('bacl', 'sources', 'serve').split():
+        ui.debug('bacl: changes have source "%s" - skipping\n' % source)
+        return
+
+    user = None
+    if source == 'serve' and 'url' in kwargs:
+        url = kwargs['url'].split(':')
+        if url[0] == 'remote' and url[1].startswith('http'):
+            user = urllib.unquote(url[3])
+            ui.debug('bacl: got user "%s" from url.\n' % user)
+
+    if user is None:
+        user = getpass.getuser()
+        ui.debug('bacl: got user "%s" from getpass.\n')
+
+    cfg = ui.config('bacl', 'config')
+    if cfg:
+        ui.readconfig(cfg, sections = ['bacl.allow', 'bacl.deny'])
+    allow = buildmatch(ui, user, 'bacl.allow')
+    deny = buildmatch(ui, user, 'bacl.deny')
+
+    for rev in xrange(repo[node], len(repo)):
+        branch = repo[rev].branch()
+        if deny and deny(branch):
+            raise util.Abort(_('bacl: user "%s" denied on branch
"%s"') % (user, branch))
+        if allow and not allow(branch):
+            raise util.Abort(_('bacl: user "%s" not allowed on branch
"%s"') % (user, branch))
+        ui.debug('bacl: allowing user "%s" on branch "%s"\n' % (user, branch))

---------------------------------------


More information about the Mercurial-devel mailing list