[PATCH] allow passing permission and ref to stdin using `access` in batch mode

19 views
Skip to first unread message

vo...@vosjedev.net

unread,
Jun 13, 2026, 2:01:43 AMJun 13
to gito...@googlegroups.com, Vosjedev
From: Vosjedev <vo...@vosjedev.net>

This commit allows passing '%' as permission and/or refname to the
`gitolite access` command. When it detects you do this, it includes both
permission and refname in the output too. For backwards-compatibility,
the format stays the same when both a permission and refname have been
passed.

Signed-off-by: Vosjedev <vo...@vosjedev.net>
---
src/commands/access | 30 ++++++++++++++++++++++++------
1 file changed, 24 insertions(+), 6 deletions(-)

diff --git a/src/commands/access b/src/commands/access
index 7d4a5b9..4edf899 100755
--- a/src/commands/access
+++ b/src/commands/access
@@ -49,13 +49,16 @@ $aa ||= '+';
# default ref is 'any'
$ref ||= 'any';
# fq the ref if needed
-$ref =~ s(^)(refs/heads/) if $ref and $ref ne 'any' and $ref !~ m(^(refs|VREF)/);
-_die "invalid perm" if not( $aa and $aa =~ /^(R|W|\+|C|D|M|\^C)$/ );
-_die "invalid ref name" if not( $ref and $ref =~ $REF_OR_FILENAME_PATT );
+if (not $ref eq '%') {
+ $ref = checkref( $ref );
+}
+if (not $aa eq '%') {
+ _die "invalid perm" if not( $aa and $aa =~ /^(R|W|\+|C|D|M|\^C)$/ );
+}

my $ret = '';

-if ( $repo ne '%' and $user ne '%' ) {
+if ( $repo ne '%' and $user ne '%' and $aa ne '%' and $ref ne '%' ) {
# single repo, single user; no STDIN
$ret = access( $repo, $user, adjust_aa($repo, $aa), $ref );

@@ -75,6 +78,8 @@ if ( $repo ne '%' and $user ne '%' ) {

$repo = '' if $repo eq '%';
$user = '' if $user eq '%';
+$aa = '' if $aa eq '%';
+$ref = '' if $ref eq '%';

_die "'-q' and '-s' meaningless in pipe mode" if $q or $s;
@ARGV = ();
@@ -82,8 +87,14 @@ while (<>) {
my @in = split;
my $r = $repo || shift @in;
my $u = $user || shift @in;
- $ret = access( $r, $u, adjust_aa($r, $aa), $ref );
- print "$r\t$u\t$ret\n";
+ my $a = $aa || shift @in;
+ my $rf = $ref || checkref( shift @in );
+ $ret = access( $r, $u, adjust_aa($r, $a), $rf );
+ if ( $aa and $ref ) {
+ print "$r\t$u\t$ret\n";
+ } else {
+ print "$r\t$u\t$a\t$rf\t$ret\n";
+ }
}

sub adjust_aa {
@@ -94,6 +105,13 @@ sub adjust_aa {
return $aa;
}

+sub checkref {
+ my $ref = shift;
+ $ref =~ s(^)(refs/heads/) if $ref and $ref ne 'any' and $ref !~ m(^(refs|VREF)/);
+ _die "invalid ref name" if not( $ref and $ref =~ $REF_OR_FILENAME_PATT );
+ return $ref
+}
+
sub show {
my $ret = shift;
die "repo already exists; ^C won't work\n" if $ret =~ /DENIED by existence/;
--
2.54.0

Sitaram Chamarty

unread,
Jun 22, 2026, 4:41:46 AM (5 days ago) Jun 22
to vo...@vosjedev.net, gito...@googlegroups.com
Hi

Sorry for the delay; as I said in private email, I was
traveling.

The patch looks OK to me, and it did pass the current test
suite.

However, I'm not quite remembering your use case. I'd like to
document somewhere the need for this, and it helps to have some
details. (It'll also help me add a script to the test suite).

sitaram
> --
> You received this message because you are subscribed to the Google Groups "gitolite" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to gitolite+u...@googlegroups.com.
> To view this discussion visit https://groups.google.com/d/msgid/gitolite/20260613053708.17014-1-vosje%40vosjedev.net.

Vosje

unread,
Jun 22, 2026, 5:14:06 AM (5 days ago) Jun 22
to Sitaram Chamarty, gito...@googlegroups.com
Good afternoon!

> Sorry for the delay; as I said in private email, I was
> traveling.
No problem, as I said, I am okay with waiting a while.

> However, I'm not quite remembering your use case. I'd like to
> document somewhere the need for this, and it helps to have some
> details. (It'll also help me add a script to the test suite).
My use case was the following: I am writing a git forge that uses
gitolite for authorisation services (and more) in the background. To
fully use this, I need to be able to query all four arguments to
gitolite and get the response back. Running a new process for every
permission check (at least one per request) was unpractical due to the
overhead the perl interpreter took to launch (I'm assuming, otherwise it
would be your init code), which was around 110ms in my vm.
Using this patch I was able to switch this process to batch mode, with
that reducing page load times by ±110ms (again on my vm, of course this
would differ per host).

The code using it can be found here:

- a module called `fastauth`, this provides the direct interface to
gitolite:
https://betagit.vosjedev.net/tree/gitsune.git/src/gitsune/fastauth.py?checkout=62051c600d19
- the `git` interface, in the commoninit function which gets called
right before generating each page:
https://betagit.vosjedev.net/tree/gitsune.git/src/gitsune/git.py?checkout=62051c600d19#LN-316
- also see line 28 in that last file where there's a wrapper around the
fastauth module, which gets called in various places around the codebase
(for example in webhooks.py to see if a user has write permission on the
repo)


> The patch looks OK to me, and it did pass the current test
> suite.
That should be correct, given I made it fully backwards-compatible. This
does however mean the current test suite does not test whether the new
output is also correct...

I hope that is enough examples, otherwise, just ask me. My code can be a
bit unreadable at times. If needed, I can write a systematic test for
the patch.

Vosjedev

(Ps. I messed up clicking `reply` instead of `reply list`, I'll do that
right next time. For now I've just added the list address to the `To`
header.)

Sitaram Chamarty

unread,
Jun 22, 2026, 9:00:10 AM (5 days ago) Jun 22
to Vosje, gito...@googlegroups.com
On Mon, Jun 22, 2026 at 11:14:01AM +0200, Vosje wrote:

> My use case was the following: I am writing a git forge that uses gitolite
> for authorisation services (and more) in the background. To fully use this,
> I need to be able to query all four arguments to gitolite and get the
> response back. Running a new process for every permission check (at least

Sounds great; this is all I need. I just wanted something to
put in the commit message for why we're doing this because the
rest of gitolite does not need this.

Give me a few more days and I will add a test script for this
functionality, and push out 3.6.15.

> - a module called `fastauth`, this provides the direct interface to
> gitolite: https://betagit.vosjedev.net/tree/gitsune.git/src/gitsune/fastauth.py?checkout=62051c600d19
> - the `git` interface, in the commoninit function which gets called right
> before generating each page: https://betagit.vosjedev.net/tree/gitsune.git/src/gitsune/git.py?checkout=62051c600d19#LN-316
> - also see line 28 in that last file where there's a wrapper around the
> fastauth module, which gets called in various places around the codebase
> (for example in webhooks.py to see if a user has write permission on the
> repo)

One possible problem. This idea works well until the access
rules are changed (by someone pushing gitolite-admin). At that
point it would be safest to reload/restart your script.

I don't know how often your gitolite-admin is changing, but you
should factor this if you haven't already.

sitaram

Vosje

unread,
Jun 23, 2026, 5:04:17 AM (4 days ago) Jun 23
to gito...@googlegroups.com
On 22/6/26 15:00, Sitaram Chamarty wrote:
> One possible problem. This idea works well until the access
> rules are changed (by someone pushing gitolite-admin). At that
> point it would be safest to reload/restart your script.
>
> I don't know how often your gitolite-admin is changing, but you
> should factor this if you haven't already.

Good point, I didn't consider what would happen if rules changed. If I
understand your point correctly, gitolite doesn't pick up on changes in
the permissions after launch? In that case, would restarting the batch
process every time the POST_CREATE hook called be enough[1]? Because as
I understand it this gets called on wildrepo permission changes too.
[1] of course I should also restart when the `gitolite-admin` repo gets
pushed, but that made the sentence too messy.
Because I already have both a hook on POST_CREATE and a git hook on
`postreceive`, that I use to clear some caches (notably every user's
repolist) when needed.

Vosjedev
Reply all
Reply to author
Forward
0 new messages