[PATCH 2 of 2 v2] acl: support revsets [RFC]
timeless
timeless at fmr.im
Thu May 5 04:45:55 EDT 2016
# HG changeset patch
# User timeless <timeless at mozdev.org>
# Date 1462327099 0
# Wed May 04 01:58:19 2016 +0000
# Node ID d4a9c04f6c504f24b7c8e228d5bff61118760573
# Parent c5ad786b58c50a6b751217f88ca1626a19c3ff30
# Available At bb://timeless/mercurial-crew
# hg pull bb://timeless/mercurial-crew -r d4a9c04f6c50
acl: support revsets [RFC]
This is an attempt to support revsets.
It works.
I can update the documentation if we want to go this route,
and add direct samples to the tests for it.
This change makes branch acl items into revset: items, which means
there is automatic testing of the revset: path.
----
An unfortunate side-effect of this change is that I've lost
the reporting indicating why a commit was rejected.
It's possible to re-engineer things so that such reporting could be
done.
----
Afaict, it does not help w/ bookmarks at all,
as bookmarks aren't applied until after the hook runs.
And I don't think one can roll back a bookmark by that point,
as I think the previous information would be lost.
diff -r c5ad786b58c5 -r d4a9c04f6c50 hgext/acl.py
--- a/hgext/acl.py Thu Mar 03 23:29:26 2016 +0000
+++ b/hgext/acl.py Wed May 04 01:58:19 2016 +0000
@@ -216,11 +216,12 @@
from __future__ import absolute_import
import getpass
+import os
from mercurial.i18n import _
from mercurial import (
error,
- match,
+ scmutil,
util,
)
@@ -277,30 +278,47 @@
ui.debug('acl: %s not enabled\n' % key)
return None
- pats = [pat for pat, users in ui.configitems(key)
+ pats = [pat.lstrip() for pat, users in ui.configitems(key)
if _usermatch(ui, user, users)]
ui.debug('acl: %s enabled, %d entries for user %s\n' %
(key, len(pats), user))
+ # Arg-based ACL
+ if not repo:
+ if not pats:
+ return util.never
+ # If there's an asterisk (meaning "any"), always return True;
+ # Otherwise, test if b is in pats
+ if '*' in pats:
+ return util.always
+ return lambda b: b in pats
+
# Branch-based ACL
- if not repo:
- if pats:
- # If there's an asterisk (meaning "any branch"), always return True;
- # Otherwise, test if b is in pats
- if '*' in pats:
- return util.always
- return lambda b: b in pats
+ if key.endswith("branches"):
+ # If there's an asterisk (meaning "any branch"), always return True;
+ # Otherwise, test if b is in pats
+ pats = [('revset:branch("%s")' % branch if branch != '*'
+ else 'revset:all()')
+ for branch in pats]
+ # Convert Path based ACL to revsets
+ revsets = [(pat[7:] if pat.startswith('revset:') else 'file("%s")' % pat)
+ for pat in pats]
+
+ if not revsets:
return util.never
- # Path-based ACL
- if pats:
- return match.match(repo.root, '', pats)
- return util.never
+ # Revset-based ACL
+ rule = ' + '.join(revsets)
+ # it might be nice to expose the rule to the client, but
+ # this API isn't particularly friendly to that.
+ criteria = '(%s) & (%s)' % (rule, '%s')
+ return lambda b: scmutil.revrange(repo, [criteria % b])
def hook(ui, repo, hooktype, node=None, source=None, **kwargs):
if hooktype not in ['pretxnchangegroup', 'pretxncommit', 'prepushkey']:
raise error.Abort(_('config error - hook type "%s" cannot stop '
- 'incoming changesets, commits, nor bookmarks') % hooktype)
+ 'incoming changesets, commits, nor bookmarks')
+ % hooktype)
if (hooktype == 'pretxnchangegroup' and
source not in ui.config('acl', 'sources', 'serve').split()):
ui.debug('acl: changes have source "%s" - skipping\n' % source)
@@ -347,30 +365,39 @@
ui.readconfig(cfg, sections=['acl.groups', 'acl.allow.branches',
'acl.deny.branches', 'acl.allow', 'acl.deny'])
- allowbranches = buildmatch(ui, None, user, 'acl.allow.branches')
- denybranches = buildmatch(ui, None, user, 'acl.deny.branches')
+ allowbranches = buildmatch(ui, repo, user, 'acl.allow.branches')
+ denybranches = buildmatch(ui, repo, user, 'acl.deny.branches')
allow = buildmatch(ui, repo, user, 'acl.allow')
deny = buildmatch(ui, repo, user, 'acl.deny')
- for rev in xrange(repo[node], len(repo)):
- ctx = repo[rev]
- branch = ctx.branch()
- if denybranches and denybranches(branch):
- raise error.Abort(_('acl: user "%s" denied on branch "%s"'
+ def checkbranches(user, ctx):
+ if denybranches and denybranches(ctx):
+ raise error.Abort(_('acl: user "%s" denied'
' (changeset "%s")')
- % (user, branch, ctx))
- if allowbranches and not allowbranches(branch):
- raise error.Abort(_('acl: user "%s" not allowed on branch "%s"'
+ % (user, ctx))
+ if allowbranches and not allowbranches(ctx):
+ raise error.Abort(_('acl: user "%s" not allowed'
' (changeset "%s")')
- % (user, branch, ctx))
- ui.debug('acl: branch access granted: "%s" on branch "%s"\n'
- % (ctx, branch))
+ % (user, ctx))
- for f in ctx.files():
- if deny and deny(f):
- raise error.Abort(_('acl: user "%s" denied on "%s"'
- ' (changeset "%s")') % (user, f, ctx))
- if allow and not allow(f):
- raise error.Abort(_('acl: user "%s" not allowed on "%s"'
- ' (changeset "%s")') % (user, f, ctx))
- ui.debug('acl: path access granted: "%s"\n' % ctx)
+ def checkctx(user, ctx):
+ if deny and deny(ctx):
+ raise error.Abort(_('acl: user "%s" denied'
+ ' (changeset "%s")') % (user, ctx))
+ if allow and not allow(ctx):
+ raise error.Abort(_('acl: user "%s" not allowed'
+ ' (changeset "%s")') % (user, ctx))
+ cwd = os.getcwd()
+ os.chdir(os.path.dirname(repo.path))
+ try:
+ for rev in xrange(repo[node], len(repo)):
+ ctx = repo[rev]
+ branch = ctx.branch()
+ checkbranches(user, ctx)
+ ui.debug('acl: branch access granted: "%s" on branch "%s"\n'
+ % (ctx, branch))
+
+ checkctx(user, ctx)
+ ui.debug('acl: path access granted: "%s"\n' % ctx)
+ finally:
+ os.chdir(cwd)
diff -r c5ad786b58c5 -r d4a9c04f6c50 tests/test-acl.t
--- a/tests/test-acl.t Thu Mar 03 23:29:26 2016 +0000
+++ b/tests/test-acl.t Wed May 04 01:58:19 2016 +0000
@@ -340,12 +340,12 @@
acl: acl.allow enabled, 0 entries for user fred
acl: acl.deny not enabled
acl: branch access granted: "ef1ea85a6374" on branch "default"
- error: pretxnchangegroup.acl hook failed: acl: user "fred" not allowed on "foo/file.txt" (changeset "ef1ea85a6374")
+ error: pretxnchangegroup.acl hook failed: acl: user "fred" not allowed (changeset "ef1ea85a6374")
bundle2-input-part: total payload size 1606
bundle2-input-bundle: 3 parts total
transaction abort!
rollback completed
- abort: acl: user "fred" not allowed on "foo/file.txt" (changeset "ef1ea85a6374")
+ abort: acl: user "fred" not allowed (changeset "ef1ea85a6374")
no rollback information available
0:6675d58eff77
@@ -410,12 +410,12 @@
acl: branch access granted: "f9cafe1212c8" on branch "default"
acl: path access granted: "f9cafe1212c8"
acl: branch access granted: "911600dab2ae" on branch "default"
- error: pretxnchangegroup.acl hook failed: acl: user "fred" not allowed on "quux/file.py" (changeset "911600dab2ae")
+ error: pretxnchangegroup.acl hook failed: acl: user "fred" not allowed (changeset "911600dab2ae")
bundle2-input-part: total payload size 1606
bundle2-input-bundle: 3 parts total
transaction abort!
rollback completed
- abort: acl: user "fred" not allowed on "quux/file.py" (changeset "911600dab2ae")
+ abort: acl: user "fred" not allowed (changeset "911600dab2ae")
no rollback information available
0:6675d58eff77
@@ -477,12 +477,12 @@
acl: acl.allow enabled, 0 entries for user barney
acl: acl.deny enabled, 0 entries for user barney
acl: branch access granted: "ef1ea85a6374" on branch "default"
- error: pretxnchangegroup.acl hook failed: acl: user "barney" not allowed on "foo/file.txt" (changeset "ef1ea85a6374")
+ error: pretxnchangegroup.acl hook failed: acl: user "barney" not allowed (changeset "ef1ea85a6374")
bundle2-input-part: total payload size 1606
bundle2-input-bundle: 3 parts total
transaction abort!
rollback completed
- abort: acl: user "barney" not allowed on "foo/file.txt" (changeset "ef1ea85a6374")
+ abort: acl: user "barney" not allowed (changeset "ef1ea85a6374")
no rollback information available
0:6675d58eff77
@@ -549,12 +549,12 @@
acl: branch access granted: "f9cafe1212c8" on branch "default"
acl: path access granted: "f9cafe1212c8"
acl: branch access granted: "911600dab2ae" on branch "default"
- error: pretxnchangegroup.acl hook failed: acl: user "fred" not allowed on "quux/file.py" (changeset "911600dab2ae")
+ error: pretxnchangegroup.acl hook failed: acl: user "fred" not allowed (changeset "911600dab2ae")
bundle2-input-part: total payload size 1606
bundle2-input-bundle: 3 parts total
transaction abort!
rollback completed
- abort: acl: user "fred" not allowed on "quux/file.py" (changeset "911600dab2ae")
+ abort: acl: user "fred" not allowed (changeset "911600dab2ae")
no rollback information available
0:6675d58eff77
@@ -620,12 +620,12 @@
acl: branch access granted: "ef1ea85a6374" on branch "default"
acl: path access granted: "ef1ea85a6374"
acl: branch access granted: "f9cafe1212c8" on branch "default"
- error: pretxnchangegroup.acl hook failed: acl: user "fred" denied on "foo/Bar/file.txt" (changeset "f9cafe1212c8")
+ error: pretxnchangegroup.acl hook failed: acl: user "fred" denied (changeset "f9cafe1212c8")
bundle2-input-part: total payload size 1606
bundle2-input-bundle: 3 parts total
transaction abort!
rollback completed
- abort: acl: user "fred" denied on "foo/Bar/file.txt" (changeset "f9cafe1212c8")
+ abort: acl: user "fred" denied (changeset "f9cafe1212c8")
no rollback information available
0:6675d58eff77
@@ -688,12 +688,12 @@
acl: acl.allow enabled, 0 entries for user barney
acl: acl.deny enabled, 0 entries for user barney
acl: branch access granted: "ef1ea85a6374" on branch "default"
- error: pretxnchangegroup.acl hook failed: acl: user "barney" not allowed on "foo/file.txt" (changeset "ef1ea85a6374")
+ error: pretxnchangegroup.acl hook failed: acl: user "barney" not allowed (changeset "ef1ea85a6374")
bundle2-input-part: total payload size 1606
bundle2-input-bundle: 3 parts total
transaction abort!
rollback completed
- abort: acl: user "barney" not allowed on "foo/file.txt" (changeset "ef1ea85a6374")
+ abort: acl: user "barney" not allowed (changeset "ef1ea85a6374")
no rollback information available
0:6675d58eff77
@@ -754,8 +754,8 @@
acl: acl.allow enabled, 1 entries for user fred
acl: acl.deny enabled, 2 entries for user fred
acl: branch access granted: "ef1ea85a6374" on branch "default"
+ invalid branchheads cache (served): tip differs
acl: path access granted: "ef1ea85a6374"
- invalid branchheads cache (served): tip differs
bundle2-input-part: total payload size 537
bundle2-input-part: "pushkey" (params: 4 mandatory) supported
calling hook prepushkey.acl: hgext.acl.hook
@@ -841,8 +841,8 @@
acl: acl.allow enabled, 1 entries for user fred
acl: acl.deny enabled, 2 entries for user fred
acl: branch access granted: "ef1ea85a6374" on branch "default"
+ invalid branchheads cache (served): tip differs
acl: path access granted: "ef1ea85a6374"
- invalid branchheads cache (served): tip differs
bundle2-input-part: total payload size 537
bundle2-input-part: "pushkey" (params: 4 mandatory) supported
calling hook prepushkey.acl: hgext.acl.hook
@@ -1020,12 +1020,12 @@
acl: branch access granted: "f9cafe1212c8" on branch "default"
acl: path access granted: "f9cafe1212c8"
acl: branch access granted: "911600dab2ae" on branch "default"
- error: pretxnchangegroup.acl hook failed: acl: user "wilma" not allowed on "quux/file.py" (changeset "911600dab2ae")
+ error: pretxnchangegroup.acl hook failed: acl: user "wilma" not allowed (changeset "911600dab2ae")
bundle2-input-part: total payload size 1606
bundle2-input-bundle: 3 parts total
transaction abort!
rollback completed
- abort: acl: user "wilma" not allowed on "quux/file.py" (changeset "911600dab2ae")
+ abort: acl: user "wilma" not allowed (changeset "911600dab2ae")
no rollback information available
0:6675d58eff77
@@ -1173,12 +1173,12 @@
acl: branch access granted: "f9cafe1212c8" on branch "default"
acl: path access granted: "f9cafe1212c8"
acl: branch access granted: "911600dab2ae" on branch "default"
- error: pretxnchangegroup.acl hook failed: acl: user "betty" not allowed on "quux/file.py" (changeset "911600dab2ae")
+ error: pretxnchangegroup.acl hook failed: acl: user "betty" not allowed (changeset "911600dab2ae")
bundle2-input-part: total payload size 1606
bundle2-input-bundle: 3 parts total
transaction abort!
rollback completed
- abort: acl: user "betty" not allowed on "quux/file.py" (changeset "911600dab2ae")
+ abort: acl: user "betty" not allowed (changeset "911600dab2ae")
no rollback information available
0:6675d58eff77
@@ -1430,12 +1430,12 @@
acl: branch access granted: "ef1ea85a6374" on branch "default"
acl: path access granted: "ef1ea85a6374"
acl: branch access granted: "f9cafe1212c8" on branch "default"
- error: pretxnchangegroup.acl hook failed: acl: user "fred" denied on "foo/Bar/file.txt" (changeset "f9cafe1212c8")
+ error: pretxnchangegroup.acl hook failed: acl: user "fred" denied (changeset "f9cafe1212c8")
bundle2-input-part: total payload size 1606
bundle2-input-bundle: 3 parts total
transaction abort!
rollback completed
- abort: acl: user "fred" denied on "foo/Bar/file.txt" (changeset "f9cafe1212c8")
+ abort: acl: user "fred" denied (changeset "f9cafe1212c8")
no rollback information available
0:6675d58eff77
@@ -1595,12 +1595,12 @@
acl: branch access granted: "ef1ea85a6374" on branch "default"
acl: path access granted: "ef1ea85a6374"
acl: branch access granted: "f9cafe1212c8" on branch "default"
- error: pretxnchangegroup.acl hook failed: acl: user "fred" denied on "foo/Bar/file.txt" (changeset "f9cafe1212c8")
+ error: pretxnchangegroup.acl hook failed: acl: user "fred" denied (changeset "f9cafe1212c8")
bundle2-input-part: total payload size 1606
bundle2-input-bundle: 3 parts total
transaction abort!
rollback completed
- abort: acl: user "fred" denied on "foo/Bar/file.txt" (changeset "f9cafe1212c8")
+ abort: acl: user "fred" denied (changeset "f9cafe1212c8")
no rollback information available
0:6675d58eff77
@@ -1808,12 +1808,12 @@
acl: path access granted: "f9cafe1212c8"
acl: branch access granted: "911600dab2ae" on branch "default"
acl: path access granted: "911600dab2ae"
- error: pretxnchangegroup.acl hook failed: acl: user "astro" denied on branch "foobar" (changeset "e8fc755d4d82")
+ error: pretxnchangegroup.acl hook failed: acl: user "astro" denied (changeset "e8fc755d4d82")
bundle2-input-part: total payload size 2101
bundle2-input-bundle: 4 parts total
transaction abort!
rollback completed
- abort: acl: user "astro" denied on branch "foobar" (changeset "e8fc755d4d82")
+ abort: acl: user "astro" denied (changeset "e8fc755d4d82")
no rollback information available
2:fb35475503ef
@@ -1840,6 +1840,7 @@
listing keys for "phases"
checking for updated bookmarks
listing keys for "bookmarks"
+ invalid branchheads cache (served): tip differs
listing keys for "bookmarks"
4 changesets found
list of changesets:
@@ -1877,12 +1878,12 @@
acl: acl.deny.branches not enabled
acl: acl.allow not enabled
acl: acl.deny not enabled
- error: pretxnchangegroup.acl hook failed: acl: user "astro" not allowed on branch "default" (changeset "ef1ea85a6374")
+ error: pretxnchangegroup.acl hook failed: acl: user "astro" not allowed (changeset "ef1ea85a6374")
bundle2-input-part: total payload size 2101
bundle2-input-bundle: 4 parts total
transaction abort!
rollback completed
- abort: acl: user "astro" not allowed on branch "default" (changeset "ef1ea85a6374")
+ abort: acl: user "astro" not allowed (changeset "ef1ea85a6374")
no rollback information available
2:fb35475503ef
@@ -1948,12 +1949,12 @@
acl: acl.deny.branches not enabled
acl: acl.allow not enabled
acl: acl.deny not enabled
- error: pretxnchangegroup.acl hook failed: acl: user "astro" not allowed on branch "default" (changeset "ef1ea85a6374")
+ error: pretxnchangegroup.acl hook failed: acl: user "astro" not allowed (changeset "ef1ea85a6374")
bundle2-input-part: total payload size 2101
bundle2-input-bundle: 4 parts total
transaction abort!
rollback completed
- abort: acl: user "astro" not allowed on branch "default" (changeset "ef1ea85a6374")
+ abort: acl: user "astro" not allowed (changeset "ef1ea85a6374")
no rollback information available
2:fb35475503ef
@@ -2208,12 +2209,12 @@
acl: acl.deny.branches enabled, 1 entries for user george
acl: acl.allow not enabled
acl: acl.deny not enabled
- error: pretxnchangegroup.acl hook failed: acl: user "george" denied on branch "default" (changeset "ef1ea85a6374")
+ error: pretxnchangegroup.acl hook failed: acl: user "george" denied (changeset "ef1ea85a6374")
bundle2-input-part: total payload size 2101
bundle2-input-bundle: 4 parts total
transaction abort!
rollback completed
- abort: acl: user "george" denied on branch "default" (changeset "ef1ea85a6374")
+ abort: acl: user "george" denied (changeset "ef1ea85a6374")
no rollback information available
2:fb35475503ef
@@ -2241,6 +2242,7 @@
listing keys for "phases"
checking for updated bookmarks
listing keys for "bookmarks"
+ invalid branchheads cache (served): tip differs
listing keys for "bookmarks"
4 changesets found
list of changesets:
@@ -2369,12 +2371,12 @@
acl: acl.deny.branches enabled, 1 entries for user george
acl: acl.allow not enabled
acl: acl.deny not enabled
- error: pretxnchangegroup.acl hook failed: acl: user "george" denied on branch "default" (changeset "ef1ea85a6374")
+ error: pretxnchangegroup.acl hook failed: acl: user "george" denied (changeset "ef1ea85a6374")
bundle2-input-part: total payload size 2101
bundle2-input-bundle: 4 parts total
transaction abort!
rollback completed
- abort: acl: user "george" denied on branch "default" (changeset "ef1ea85a6374")
+ abort: acl: user "george" denied (changeset "ef1ea85a6374")
no rollback information available
2:fb35475503ef
More information about the Mercurial-devel
mailing list