Skip to content

Commit

Permalink
new command: option
Browse files Browse the repository at this point in the history
  • Loading branch information
sitaramc committed Dec 30, 2014
1 parent cb273f3 commit 90e47e1
Showing 1 changed file with 127 additions and 0 deletions.
127 changes: 127 additions & 0 deletions src/commands/option
@@ -0,0 +1,127 @@
#!/usr/bin/perl

# ----------------------------------------------------------------------
# gitolite command to allow repo "owners" to set "options" on repos

# This command can be run by a user to set "options" for any repo that she
# owns.
#
# However, gitolite does *not* have the concept of an incremental "compile",
# and options are only designed to be specified in the gitolite.conf file
# (which a user should not be able to even see!). Therefore, we allow one
# specific file (conf/options.conf) to be manipulated by a remote user in a
# *controlled* fashion, and this file is "include"d in the main gitolite.conf
# file.

# WARNINGS:
# 1. Runs "gitolite compile" at the end. On really huge systems (where the
# sum total of the conf files is in the order of tens of thousands of
# lines) this may take a second or two :)
# 2. Since "options.conf" is not part of the admin repo, you may need to
# back it up separately, just like you currently back up gl-creator and
# gl-perms files from individual repos.
# 3. "options.conf" is formatted very strictly because it's not meant to be
# human edited. If you edit it directly on the server, be careful.

# Relevant gitolite doc links:
# "wild" repos and "owners"
# http://gitolite.com/gitolite/wild.html
# http://gitolite.com/gitolite/wild.html#specifying-owners
# http://gitolite.com/gitolite/wild.html#appendix-1-owner-and-creator
# gitolite "options"
# http://gitolite.com/gitolite/options.html
# the "include" statement
# http://gitolite.com/gitolite/conf.html#include

# setup:
# 1. Enable the command by adding it to the ENABLE list in the rc file.
#
# 2. Make sure your gitolite.conf has this line at the end:
#
# include "options.conf"
#
# then add/commit/push.
#
# Do NOT add a file called "options.conf" to your gitolite-admin repo!
# This means every time you compile (push the admin repo) you will get a
# warning about the missing file.
#
# You can either "touch ~/.gitolite/conf/options.conf" on the server, or
# take *any* wild repo and add *any* option to create it.
#
# 3. Specify options allowed to be changed by the user. For example:
#
# repo foo/..*
# C = blah blah
# ...other rules...
# option user-options = hook\..* foo bar[0-9].*
#
# Users can then set any of these options, but no others.

# ----------------------------------------------------------------------

use strict;
use warnings;

use lib $ENV{GL_LIBDIR};
use Gitolite::Easy;
use Gitolite::Common;

# ----------------------------------------------------------------------
# usage and arg checks

=for usage
Usage: ssh git@host option <repo> add <key> <val>
ssh git@host option <repo> del <key>
ssh git@host option <repo> list
Add, delete, or list options for wild repos. Keys must match one of the
allowed patterns; your system administrator will tell you what they are.
Doesn't check things like adding a key that already exists (simply overwrites
without warning), deleting a key that doesn't, etc.
=cut

usage() if not @ARGV or $ARGV[0] eq '-h';

my $OPTIONS = "$ENV{HOME}/.gitolite/conf/options.conf";

my $repo = shift;
die "sorry, you are not authorised\n" unless owns($repo);

my $op = shift; usage() unless $op =~ /^(add|del|list)$/;
my $key = shift; usage() if not $key and $op ne 'list';
my $val = shift; usage() if not $val and $op eq 'add';

_print( $OPTIONS, "" ) unless -f $OPTIONS; # avoid error on first run
my $options = slurp($OPTIONS);

# ----------------------------------------------------------------------
# get 'list' out of the way first
if ( $op eq 'list' ) {
print "$1\t$2\n" while $options =~ /^repo $repo\n option (\S+) = (.*)/mg;
exit 0;
}

# ----------------------------------------------------------------------
# that leaves 'add' or 'del'

# NOTE: sanity check on characters in key and val not needed;
# REMOTE_COMMAND_PATT is more restrictive than UNSAFE_PATT anyway!

# check if the key is allowed
my $user_options = option( $repo, 'user-options' );
# this is a space separated list of allowed option keys
my @validkeys = split( ' ', ( $user_options || '' ) );
my @matched = grep { $key =~ /^$_$/i } @validkeys;
_die "option '$key' not allowed\n" if ( @matched < 1 );

# delete anyway
$options =~ s/^repo $repo\n option $key = .*\n//m;
# then re-add if needed
$options .= "repo $repo\n option $key = $val\n" if $op eq 'add';

# ----------------------------------------------------------------------
# save and compile
_print( $OPTIONS, $options );
system("gitolite compile");

0 comments on commit 90e47e1

Please sign in to comment.