merge in branch support fixes
authorPaul Crowley <paul@lshift.net>
Tue, 22 Apr 2008 13:03:17 +0100
changeset 23 9fa62cfd2821
parent 19 62ee928ac9b3 (current diff)
parent 22 578555227599 (diff)
child 24 9f8e11ede780
merge in branch support fixes
access.py
hg-ssh
ruleset.py
--- a/README	Tue Apr 22 12:55:56 2008 +0100
+++ b/README	Tue Apr 22 13:03:17 2008 +0100
@@ -132,6 +132,7 @@
 user=<globpattern> - user's key
 repo=<globpattern> - repo (as the user supplies it)
 file=<globpattern> - file in the repo
+branch=<globpattern> - name of the branch
 
 The first rule in the file which has all its conditions satisfied is
 used to determine whether an action is allowed.
@@ -145,10 +146,11 @@
 
 FILE CONDITIONS
 
-The rules file is used to make three decisions:
+The rules file is used to make four decisions:
 
 - Whether to allow a repository to be created
 - Whether to allow access to a repository
+- Whether to allow a changeset on a particular branch at all
 - Whether to allow a changeset to change a particular file
 
 When the first two of these decisions are being made, nothing is known
@@ -172,6 +174,18 @@
 
 - For similar reasons, don't give "init" rules file conditions.
 
+LOCKING YOURSELF OUT
+
+If you find yourself "locked out" - that is, that you no longer have
+the permissions needed in hgadmin - you can break back in again if
+you're able to become the "hg" user on the repository host.  Once you
+are that user, delete ~hg/.ssh/authorized_keys (to stop any user who
+might have access but shouldn't from using the repository while you
+fix things).  Then go into ~hg/repos/hgadmin, do an "hg update", edit
+things to your satisfaction, and commit the change.  Finally, run
+~/admin/hg-admin-tools/refresh-auth to regenerate
+~hg/.ssh/authorized_keys. 
+
 THANKS
 
 Thanks for reading this far.  If you use hg-admin-tools, please tell
--- a/access.py	Tue Apr 22 12:55:56 2008 +0100
+++ b/access.py	Tue Apr 22 13:03:17 2008 +0100
@@ -21,21 +21,32 @@
     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 = ruleset.Ruleset.readfile(os.environ['HG_ACCESS_RULES_FILE'])
+        self.rules.set(user = os.environ['REMOTE_USER'])
+        self.rules.set(repo = os.environ['HG_REPO_PATH'])
+
+    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", branch=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", branch=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):
-        '''return if access allowed, raise exception if not.'''
-        files = self.repo.changectx(node).files()
-        for f in files:
-            if not self.rules.allow("write", user=self.user, repo=self.repo_path, file=f):
-                self.ui.debug(_('%s: user %s not allowed on %s\n') %
-                              (__name__, self.getuser(), f))
-                raise util.Abort(_('%s: access denied for changeset %s') %
-                                 (__name__, short(node)))
-        self.ui.debug(_('%s: allowing changeset %s\n') % (__name__, short(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 '
--- a/hg-ssh	Tue Apr 22 12:55:56 2008 +0100
+++ b/hg-ssh	Tue Apr 22 13:03:17 2008 +0100
@@ -48,15 +48,15 @@
         fail("Disallowing path: %s" % path)
     return path
 
-def get_cmd(rules, remoteuser, cmd):
+def get_cmd(rules, cmd):
     if cmd.startswith('hg -R ') and cmd.endswith(' serve --stdio'):
         repo = getpath(cmd[6:-14])
-        if rules.allow("read", user=remoteuser, repo=repo, file=None):
+        if rules.allow("read", repo=repo):
             os.environ["HG_REPO_PATH"] = repo
             return ['-R', repo, 'serve', '--stdio']
     elif cmd.startswith('hg init '):
         repo = getpath(cmd[8:])
-        if rules.allow("init", user=remoteuser, repo=repo, file=None):
+        if rules.allow("init", repo=repo):
             os.environ["HG_REPO_PATH"] = repo
             return ['init', repo]
     fail("Illegal command %r" % cmd)
@@ -69,8 +69,9 @@
         % sys.argv)
 
 rules = ruleset.Ruleset.readfile(os.environ['HG_ACCESS_RULES_FILE'])
-remoteuser = getpath(os.environ['REMOTE_USER'])
-todispatch = get_cmd(rules, remoteuser, 
+rules.set(remoteuser = getpath(os.environ['REMOTE_USER']))
+rules.set(branch = None, file = None)
+todispatch = get_cmd(rules, 
     os.environ.get('SSH_ORIGINAL_COMMAND', '?'))
 dispatch.dispatch(todispatch)
 
--- a/ruleset.py	Tue Apr 22 12:55:56 2008 +0100
+++ b/ruleset.py	Tue Apr 22 13:03:17 2008 +0100
@@ -50,13 +50,20 @@
 
     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 matchrule(self, **kw):
+        d = self.preset.copy()
+        d.update(**kw)
         for a, c in self.rules:
-            if c(**kw):
+            if c(**d):
                 return a
         return None
 
@@ -78,5 +85,3 @@
         finally:
             f.close()
         return res
-
-