Merge branch 'master' into wildrepos

master brought in:

  - full email addresses as usernames
  - repo-specific git config

Conflicts:
	doc/3-faq-tips-etc.mkd
	src/gitolite.pm
	src/gl-compile-conf
This commit is contained in:
Sitaram Chamarty 2009-12-11 11:19:54 +05:30
commit ff28acb059
6 changed files with 169 additions and 26 deletions

View file

@ -6,9 +6,13 @@
# the description string for gitweb)
# - comments in the normal shell-ish style; no surprises there
# - there are NO continuation lines of any kind
# - user/repo names as simple as possible
# (usernames: only alphanumerics, ".", "_", "-";
# reponames: same, plus "/", but not at the start)
# - user/repo names as simple as possible; they must start with an
# alphanumeric, but after that they can also contain ".", "_", "-".
# - usernames can optionally be followed by an "@" and a domainname
# containing at least one "." (this allows you to use an email
# address as someone's username)
# - reponames can contain "/" characters (this allows you to
# put your repos in a tree-structure for convenience)
# objectives, over and above gitosis:
# - simpler syntax
@ -87,7 +91,8 @@
repo gitolite-admin
RW+ = @admins
# "@all" is a special, predefined, group name
# "@all" is a special, predefined, group name of all users
# (everyone who has a pubkey in keydir)
repo testing
RW+ = @all
@ -181,3 +186,26 @@ repo linux perl
# give gitweb access as described above if you're specifying a description
gitolite "Sitaram Chamarty" = "fast, secure, access control for git in a corporate environment"
# REPO SPECIFIC GITCONFIG
# -----------------------
# (Thanks to teemu dot matilainen at iki dot fi)
# this should be specified within a "repo" stanza
# syntax:
# config sectionname.keyname = [optional value_string]
# example usage: if you placed a hook in src/hooks that requires configuration
# information that is specific to each repo, you could do this:
repo gitolite
config hooks.mailinglist = gitolite-commits@example.tld
config hooks.emailprefix = "[gitolite] "
config foo.bar = ""
config foo.baz =
# This does either a plain "git config section.key value" (for the first 3
# examples above) or "git config --unset-all section.key" (for the last
# example). Other forms (--add, the value_regex, etc) are not supported.

View file

@ -37,13 +37,16 @@ Assumptions/pre-requisites:
* git is installed on that server (and so is perl)
* you have a userid on that server
* you have ssh-pubkey (**password-less**) login to that userid
* (if you have only password access, run `ssh-keygen -t rsa` to create a
new keypair if needed, then run `ssh-copy-id user@host`)
* if you have only password access, run `ssh-keygen -t rsa` to create a
new keypair if needed, then run `ssh-copy-id user@host`. If you do
not have `ssh-copy-id`, read doc/3-faq-tips-etc.mkd and look for
`ssh-copy-id` in that file for instructions
* you have a clone or an archive of gitolite somewhere on your workstation
* if you don't have one, just run `git clone git://github.com/sitaramc/gitolite`
If so, just `cd` to that clone and run `src/gl-easy-install` and follow the
prompts! (Running it without any arguments shows you usage plus other useful
info).
Once you have all this, just `cd` to that clone and run `src/gl-easy-install`
and follow the prompts! (Running it without any arguments shows you usage
plus other useful info).
#### typical example run

View file

@ -9,6 +9,7 @@ In this document:
* adding users and repos
* specifying gitweb and daemon access
* custom hooks
* custom git config
### administer
@ -90,3 +91,25 @@ just run easy install once again; it'll do it to existing repos also.
implements all the branch-level permissions in gitolite. If you fiddle with
the hooks directory, please make sure you do not mess with this file
accidentally, or all your fancy per-branch permissions will stop working.**
#### custom git config
The custom hooks feature is a blunt instrument -- all repos get the hook you
specified and will run it. In order to make it a little more fine-grained,
you could set your hooks to only work if a certain "gitconfig" variable was
set. Which means we now need a way to specify "git config" settings on a per
repository basis.
Thanks to Teemu (teemu dot matilainen at iki dot fi), gitolite now does this
very easily. For security reasons, this can only be done from the master
config file (i.e., if you're using delegation, the delegated admins cannot
specify git config settings).
Please see `conf/example.conf` for syntax. Note that this only supports the
basic forms of the "git config" command:
git config section.key value # value may be an empty string
git config --unset-all section.key
It does not (currently) support other options like `--add`, the `value_regex`,
etc.

View file

@ -19,22 +19,32 @@ In this document:
* what repos do I have access to?
* "exclude" (or "deny") rules
* "personal" branches
* custom hooks and custom git config
* repos named with wildcards
* design choices
* keeping the parser and the access control separate
### common errors and mistakes
* forgetting to suffix `.git` to the end of the reponame in the `git clone`.
This suffix is *not* used in the gitolite config file for the sake of
clarity and cleaner syntax, but don't let that fool you. It's a
convention in the git world that **bare repos** end with `.git`.
* adding `repositories/` at the start of the repo name in the `git clone`.
This error is typically made by the *admin* himself -- because he knows
what `$REPO_BASE` is set to and thinks he has to provide that prefix on
the client side also :-) In fact gitolite prepends `$REPO_BASE` when it
is required anyway, so you shouldn't do the same thing!
the client side also :-) In fact gitolite prepends `$REPO_BASE`
internally, so you shouldn't also do the same thing!
* being able to clone but getting errors on push. Most likely caused by a
combination of:
* you already have shell access to the server, not just "gitolite"
access, *and*
* you cloned using `git clone git@server:repositories/repo.git` (notice
there's an extra "repositories/" in there?)
In other words, you used a key that completely bypassed gitolite and went
straight to the shell to do the clone.
Please see doc/6-ssh-troubleshooting.mkd for what all this means.
### git version dependency
@ -67,6 +77,27 @@ normal way, since it's not empty anymore.
### other errors, warnings, notes...
* don't have `ssh-copy-id`? This is broadly what that command does, if you
want to replicate it manually. The input is your pubkey, typically
`~/.ssh/id_rsa.pub` from your client/workstation.
* it copies it to the server as some file
* it appends that file to `~/.ssh/authorized_keys` on the server
(creating it if it doesn't already exist)
* it then makes sure that all these files/directories have go-w perms
set (assuming user is "git"):
/home/git/.ssh/authorized_keys
/home/git/.ssh
/home/git
[Actually, sshd requires that even directories *above* ~ (/, /home,
typically) also must be `go-w`, but that needs root. And typically
they're already set that way anyway. (Or if they're not, you've got
bigger problems than gitolite install not working!)]
* cloning an empty repo is only possible with clients greater than 1.6.2.
So at least one of your clients needs to have a recent git. Once at least
one commit has been made, older clients can also use it
@ -345,12 +376,36 @@ gitolite knows these two keys belong to the same person.
Note that you don't say "sitaram@laptop" and so on in the **config** file --
as far as the config file is concerned there's just **one** user called
"sitaram" -- so you only say "sitaram" there. Only the **pubkey files** have
the extra "@" stuff.
"sitaram" -- so you only say "sitaram" there.
I think this is easier to maintain if you have to delete or change one of
those keys.
However, now that `sitaramc@gmail.com` is also a valid username, we need to
distinguish between `sitaramc@gmail.com.pub` and `sitaramc@desktop.pub`. We
do that by requiring that the multi-key suffix you use (like "desktop" and
"laptop") should not have a `"."` in it. If it does, it looks like an email
address. The following table lists sample pubkey filenames and the
corresponding derived usernames (which is what goes into the
`conf/gitolite.conf` file):
* old style multikeys; not mistaken for emails because there is no "." in
hostname part
sitaramc.pub sitaramc
sitaramc@laptop.pub sitaramc
sitaramc@desktop.pub sitaramc
* new style, email keys; there is a "." in hostname part; so it's an email
address
sitaramc@gmail.com.pub sitaramc@gmail.com
* multikeys *with* email address
sitaramc@gmail.com@laptop.pub sitaramc@gmail.com
sitaramc@gmail.com@desktop.pub sitaramc@gmail.com
#### support for git installed outside default PATH
The normal solution is to add to the system default PATH somehow, either by
@ -507,6 +562,12 @@ first check:
Just don't *show* the user this config file; it might sound insulting :-)
#### custom hooks and custom git config
You can specify hooks that you want to propagate to all repos, as well as
per-repo "gitconfig" settings. Please see `doc/2-admin.mkd` and
`conf/example.conf` for details.
#### repos named with wildcards
**This feature only exists in the "wildrepos" branch!** Please see

View file

@ -24,9 +24,9 @@ $WARN = "\n\t\t***** WARNING *****\n ";
$R_COMMANDS=qr/^(git[ -]upload-pack|git[ -]upload-archive)$/;
$W_COMMANDS=qr/^git[ -]receive-pack$/;
# note that REPONAME_PATT allows a "/" also, which USERNAME_PATT doesn't
# note that REPONAME_PATT allows "/", while USERNAME_PATT allows "@"
$REPONAME_PATT=qr(^\@?[0-9a-zA-Z][0-9a-zA-Z._/-]*$); # very simple pattern
$USERNAME_PATT=qr(^\@?[0-9a-zA-Z][0-9a-zA-Z._-]*$); # very simple pattern
$USERNAME_PATT=qr(^\@?[0-9a-zA-Z][0-9a-zA-Z._\@-]*$); # very simple pattern
# same as REPONAME, plus some common regex metas
$REPOPATT_PATT=qr(^\@?[0-9a-zA-Z][\\^.$|()[\]*+?{}0-9a-zA-Z._/-]*$);

View file

@ -36,11 +36,11 @@ $Data::Dumper::Sortkeys = sub { return [ reverse sort keys %{$_[0]} ]; };
# - anytime a pubkey is added/deleted
# - anytime gitolite.conf is changed
# input:
# - GL_CONF (default: ~/.gitolite/gitolite.conf)
# - GL_CONF (default: ~/.gitolite/conf/gitolite.conf)
# - GL_KEYDIR (default: ~/.gitolite/keydir)
# output:
# - ~/.ssh/authorized_keys (dictated by sshd)
# - GL_CONF_COMPILED (default: ~/.gitolite/gitolite.conf-compiled.pm)
# - GL_CONF_COMPILED (default: ~/.gitolite/conf/gitolite.conf-compiled.pm)
# security:
# - touches a very critical system file that manages the restrictions on
# incoming users. Be sure to audit AUTH_COMMAND and AUTH_OPTIONS (see
@ -111,6 +111,9 @@ my %rurp_seen = ();
# catch usernames<->pubkeys mismatches; search for "lint" below
my %user_list = ();
# repo configurations
my %repo_config = ();
# gitweb descriptions and owners; plain text, keyed by "$repo.git"
my %desc = ();
my %owner = ();
@ -129,7 +132,7 @@ sub expand_list
for my $item (@list)
{
die "$ABRT bad user or repo name $item\n" unless $item =~ $REPOPATT_PATT;
die "$ABRT bad user or repo name $item\n" unless $item =~ $REPOPATT_PATT or $item =~ $USERNAME_PATT;
if ($item =~ /^@/) # nested group
{
die "$ABRT undefined group $item\n" unless $groups{$item};
@ -182,7 +185,6 @@ sub parse_conf_file
# store the members of each group as hash key. Keep track of when
# the group was *first* created by using $fragment as the *value*
do { $groups{$1}{$_} ||= $fragment } for ( expand_list( split(' ', $2) ) );
# again, we take the more "relaxed" pattern
die "$ABRT bad group $1\n" unless $1 =~ $REPONAME_PATT;
}
# repo(s)
@ -278,6 +280,16 @@ sub parse_conf_file
}
}
}
# configuration
elsif (/^config (.+) = ?(.*)/)
{
my ($key, $value) = ($1, $2);
die "$WARN $fragment attempting to set repo configuration\n" if $fragment ne 'master';
for my $repo (@repos) # each repo in the current stanza
{
$repo_config{$repo}{$key} = $value;
}
}
# very simple syntax for the gitweb description of repo; one of:
# reponame = "some description string"
# reponame "owner name" = "some description string"
@ -379,6 +391,22 @@ warn "\n\t\t***** WARNING *****\n" .
"\t\"git version dependency\" in doc/3-faq-tips-etc.mkd\n"
if $git_version < 10602; # that's 1.6.2 to you
# ----------------------------------------------------------------------------
# update repo configurations
# ----------------------------------------------------------------------------
for my $repo (keys %repo_config) {
wrap_chdir("$repo_base_abs/$repo.git");
while ( my ($key, $value) = each(%{ $repo_config{$repo} }) ) {
if ($value) {
$value =~ s/^"(.*)"$/$1/;
system("git", "config", $key, $value);
} else {
system("git", "config", "--unset-all", $key);
}
}
}
# ----------------------------------------------------------------------------
# handle gitweb and daemon
# ----------------------------------------------------------------------------
@ -450,7 +478,7 @@ for my $pubkey (glob("*"))
print STDERR "WARNING: pubkey files should end with \".pub\", ignoring $pubkey\n";
next;
}
my $user = $pubkey; $user =~ s/(\@.+)?\.pub$//;
my $user = $pubkey; $user =~ s/(\@[^.]+)?\.pub$//;
# lint check 2
print STDERR "WARNING: pubkey $pubkey exists but user $user not in config\n"
unless $user_list{$user};