Merge branch 'master' into wildrepos

Conflicts:
	src/hooks/update
This commit is contained in:
Sitaram Chamarty 2010-01-14 20:47:04 +05:30
commit bede47e2db
11 changed files with 359 additions and 81 deletions

View file

@ -170,6 +170,40 @@ repo git
# looking for (`W` or `+`), or a minus (`-`), results in success, or failure, # looking for (`W` or `+`), or a minus (`-`), results in success, or failure,
# respectively. A fallthrough also results in failure # respectively. A fallthrough also results in failure
# FILE/DIR NAME BASED RESTRICTIONS
# --------------------------------
# Here's a hopefully self-explanatory example. Assume the project has the
# following contents at the top level: a README, a "doc/" directory, and an
# "src/" directory.
repo foo
RW+ = lead_dev # rule 1
RW = dev1 dev2 dev3 dev4 # rule 2
RW NAME/ = lead_dev # rule 3
RW NAME/doc/ = dev1 dev2 # rule 4
RW NAME/src/ = dev1 dev2 dev3 dev4 # rule 5
# Notes
# - the "NAME/" is part of the syntax; think of it as a keyword if you like
# - file/dir NAME-based restrictions are *in addition* to normal (branch-name
# based) restrictions; they are not a *replacement* for them. This is why
# rule #2 (or something like it, maybe with a more specific branch-name) is
# needed; without it, dev1/2/3/4 cannot push any branches.
# - if a repo has *any* NAME/ rules, then NAME-based restrictions are checked
# for *all* users. This is why rule 3 is needed, even though we don't
# actually have any NAME-based restrictions on lead_dev. Notice the pattern
# on rule 3.
# - *each* file touched by the commits being pushed is checked against those
# rules. So, lead_dev can push changes to any files, dev1/2 can push
# changes to files in "doc/" and "src/" (but not the top level README), and
# dev3/4 can only push changes to files in "src/".
# GITWEB AND DAEMON STUFF # GITWEB AND DAEMON STUFF
# ----------------------- # -----------------------
@ -217,19 +251,3 @@ repo gitolite
# This does either a plain "git config section.key value" (for the first 3 # 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 # examples above) or "git config --unset-all section.key" (for the last
# example). Other forms (--add, the value_regex, etc) are not supported. # example). Other forms (--add, the value_regex, etc) are not supported.
# SHELL ACCESS
# ------------
# It is possible to give certain users shell access as well as allow them to
# use gitolite features for their git repo access. The idea is to eliminate
# the need for 2 keys when both shell and gitolite access are needed.
# To give a user shell access, add the username to the special @SHELL group:
@SHELL = sitaram
# Do not add people to this group indiscriminately. AUDITABILITY OF ACCESS
# CONTROL CHANGES (AND OF REPO ACCESSES) WILL BE COMPROMISED IF ADMINS CAN
# FIDDLE WITH THE ACTUAL (PLAIN TEXT) LOG FILES THAT GITOLITE KEEPS, WHICH
# THEY CAN EASILY DO IF THEY HAVE A SHELL.

View file

@ -93,6 +93,19 @@ $PERSONAL="";
$GIT_PATH=""; $GIT_PATH="";
# $GIT_PATH="/opt/bin/"; # $GIT_PATH="/opt/bin/";
# --------------------------------------
# if you want to give shell access to any gitolite user(s), name them here.
# Please see doc/6-ssh-troubleshooting.mkd for details on how this works.
# Do not add people to this list indiscriminately. AUDITABILITY OF ACCESS
# CONTROL CHANGES (AND OF REPO ACCESSES) WILL BE COMPROMISED IF ADMINS CAN
# FIDDLE WITH THE ACTUAL (PLAIN TEXT) LOG FILES THAT GITOLITE KEEPS, WHICH
# THEY CAN EASILY DO IF THEY HAVE A SHELL.
# syntax: space separated list of gitolite usernames in *one* string variable.
# $SHELL_USERS = "alice bob";
# -------------------------------------- # --------------------------------------
# per perl rules, this should be the last line in such a file: # per perl rules, this should be the last line in such a file:
1; 1;

View file

@ -13,6 +13,7 @@ In this document:
* differences from gitosis * differences from gitosis
* simpler syntax * simpler syntax
* two levels of access rights checking * two levels of access rights checking
* file/dir NAME based restrictions
* error checking the config file * error checking the config file
* delegating parts of the config file * delegating parts of the config file
* easier to specify gitweb "description" and gitweb/daemon access * easier to specify gitweb "description" and gitweb/daemon access
@ -236,6 +237,15 @@ any of the refexes match, the push succeeds. If none of them match, it fails.
Gitolite also allows "exclude" or "deny" rules. See later in this document Gitolite also allows "exclude" or "deny" rules. See later in this document
for details. for details.
#### file/dir NAME based restrictions
In addition to branch-name based restrictions, gitolite also allows you to
restrict what files or directories can be involved in changes being pushed.
This basically uses `git diff --name-only` to obtain the list of files being
changed, treating each filename as a "ref" to be matched.
Please see `conf/example.conf` for syntax and examples.
#### error checking the config file #### error checking the config file
gitosis does not do any. I just found out that if you mis-spell `members` as gitosis does not do any. I just found out that if you mis-spell `members` as

View file

@ -61,35 +61,35 @@ You do this by adding branches to the `gitolite-admin` repo:
# the admin repo access was probably like this to start with: # the admin repo access was probably like this to start with:
repo gitolite-admin repo gitolite-admin
RW+ = sitaram RW+ = sitaram
# now add these lines to the config for the admin repo # now add these lines to the config for the admin repo
RW webbrowser_repos = alice RW NAME/conf/fragments/webbrowser_repos = alice
RW webserver_repos = bob RW NAME/conf/fragments/webserver_repos = bob
RW malware_repos = mallory RW NAME/conf/fragments/malware_repos = mallory
This uses gitolite's ability to restrict pushes by file/dir name being changed
-- the syntax you see above ensures that, while "sitaram" does not have any
NAME based restrictions, the other 3 users do. See `conf/example.conf` for
syntax and notes.
As you can see, **for each repo group** you want to delegate authority over, As you can see, **for each repo group** you want to delegate authority over,
there's a **branch with the same name** in the `gitolite-admin` repo. If you there's a rule for a **corresponding file** in `conf/fragments` in the
have write access to that branch, you are allowed to define rules for repos in `gitolite-admin` repo. If you have write access to that file, you are allowed
that repo group. to define rules for repos in that repo group.
In other words, we use gitolite's per-branch permissions to "enforce" the In other words, we use gitolite's file/dir NAME-based permissions to "enforce"
separation between the delegated configs! the separation between the delegated configs!
Here's how to use this in practice: Here's how to use this in practice:
* Alice clones the `gitolite-admin` repo, creates (if not already created) and * Alice clones the `gitolite-admin` repo, and adds a file called
checks out a new branch called `webbrowser_repos`, and adds a file called `conf/fragments/webbrowser_repos.conf`
`conf/fragments/webbrowser_repos.conf` in that branch
* (the rest of the contents of that branch do not matter; she can keep
all the other files or delete all of them -- it doesn't make any
difference. Only that one specific file is used).
* she writes in this file any access control rules for the "firefox" and * she writes in this file any access control rules for the "firefox" and
"lynx" repos. She should not write access rules for any other project -- "lynx" repos. She should not write access rules for any other project --
they will be ignored they will be ignored
* Alice then commits and pushes this branch to the `gitolite-admin` repo * Alice then commits and pushes to the `gitolite-admin` repo
Naturally, a successful push invokes the post-update hook that the admin repo Naturally, a successful push invokes the post-update hook that the admin repo
has, which eventually runs the compile script. The **net effect** is as if has, which eventually runs the compile script. The **net effect** is as if

View file

@ -8,10 +8,34 @@ and shell access]...". We've managed (thanks to an idea from Jesse Keating)
to get around this. Now it *is* possible for a single key to allow both to get around this. Now it *is* possible for a single key to allow both
gitolite access *and* shell access. gitolite access *and* shell access.
This is done by placing such a user in a special `@SHELL` group in the This is done by:
gitolite config file. As usual, please see `conf/example.conf` for more info
on this, since I'm using that as a central place to document anything * (**on the server**) listing all such users in a variable called
concerned with the conf file. `$SHELL_USERS` in the `~/.gitolite.rc` file. For example:
$SHELL_USERS = "alice bob";
(Note the syntax: a space separated list of users in one string variable).
* (**on your client**) make at least a dummy change to your clone of the
gitolite-admin repo and push it.
**IMPORTANT UPGRADE NOTE**: a previous implementation of this feature worked
by adding people to a special group (`@SHELL`) in the *config* file. This
meant that anyone with gitolite-admin repo write access could add himself to
the `@SHELL` group and push, thus obtaining shell.
This is not a problem for most setups, but if someone wants to separate these
two privileges (the right to push the admin repo and the right to get a shell)
then it does pose a problem. Since the "rc" file can only be edited by
someone who already has shell access, we now use that instead, even though
this forces a change in the syntax.
To migrate from the old scheme to the new one, add a new variable
`$SHELL_USERS` to `~/.gitolite.rc` on the server with the appropriate names in
it. **It is best to do this directly on the server *before* upgrading to this
version.** (After the upgrade is done and tested you can remove the `@SHELL`
lines from the gitolite config file).
---- ----

View file

@ -0,0 +1,211 @@
# gitolite install transcript
This is a *complete* transcript of a full gitolite install, *from scratch*,
using brand new userids ("sita" on the client, "git" on the server). Please
note that you can use existing userids also, it is not necessary to use
dedicated user IDs for this. Also, you don't have to use some *other* server
for all this, both server and client can be "localhost" if you like.
Please note that this entire transcript can be summarised as:
* create users on client and server (optional)
* get pubkey access to server from client (`ssh-copy-id` or manual eqvt)
* run one command ***on client*** (`gl-easy-install`)
...and only that last step is actually gitolite. In fact, the bulk of the
transcript is **non**-gitolite stuff :)
----
### create userids on server and client (optional)
Client side: add user, give him a password
sita-lt:~ # useradd sita
sita-lt:~ # passwd sita
Changing password for user sita.
New UNIX password:
Retype new UNIX password:
passwd: all authentication tokens updated successfully.
Server side: (log on to server, then) add user, give it a password
sita-lt:~ # ssh sitaram@server
sitaram@server's password:
Last login: Fri Dec 18 20:25:06 2009
-bash-3.2$ su -
Password:
sita-sv:~ # useradd git
sita-sv:~ # passwd git
Changing password for user git.
New UNIX password:
Retype new UNIX password:
passwd: all authentication tokens updated successfully.
Server side: allow ssh access to "git" user
This is done by editing the sshd config file and adding "git" to the
"AllowUsers" list (the grep command is just confirming the change we made,
because I'm not showing the actual "vi" session):
sita-sv:~ # vim /etc/ssh/sshd_config
sita-sv:~ # grep -i allowusers /etc/ssh/sshd_config
AllowUsers sitaram git
sita-sv:~ # service sshd restart
Stopping sshd: [ OK ]
Starting sshd: [ OK ]
----
### get pubkey access from client to server
This involves creating a keypair for yourself (using `ssh-keygen`), and
copying the public part of that keypair to the `~/.ssh/authorized_keys` file
on the server (using `ssh-copy-id`, if you're on Linux, or the manual method
described in the `ssh-copy-id` section in `doc/3-faq-tips-etc.mkd`).
sita-lt:~ $ su - sita
Password:
sita@sita-lt:~ $ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/sita/.ssh/id_rsa):
Created directory '/home/sita/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/sita/.ssh/id_rsa.
Your public key has been saved in /home/sita/.ssh/id_rsa.pub.
The key fingerprint is:
8a:e0:60:1b:04:58:68:50:a4:d7:d0:3a:a5:2d:bf:0a sita@sita-lt.atc.tcs.com
The key's randomart image is:
+--[ RSA 2048]----+
|===. |
|+o oo |
|o..=. |
|..= . |
|.o.+ S |
|.oo... . |
|E.. ... |
| . . |
| .. |
+-----------------+
sita@sita-lt:~ $ ssh-copy-id -i ~/.ssh/id_rsa git@server
git@server's password:
/usr/bin/xauth: creating new authority file /home/git/.Xauthority
Now try logging into the machine, with "ssh 'git@server'", and check in:
.ssh/authorized_keys
to make sure we haven't added extra keys that you weren't expecting.
Double check to make sure you can log on to `git@server` without a password:
sita@sita-lt:~ $ ssh git@server pwd
/home/git
----
### get gitolite source
sita@sita-lt:~ $ git clone git://github.com/sitaramc/gitolite gitolite-source
Initialized empty Git repository in /home/sita/gitolite-source/.git/
remote: Counting objects: 1157, done.
remote: Compressing objects: 100% (584/584), done.
remote: Total 1157 (delta 756), reused 912 (delta 562)
Receiving objects: 100% (1157/1157), 270.08 KiB | 61 KiB/s, done.
Resolving deltas: 100% (756/756), done.
### install gitolite
Note that gitolite is installed from the *client*. The `easy-install` script
runs on the client but installs gitolite on the server!
sita@sita-lt:~ $ cd gitolite-source/src
<font color="red"> **This is the only gitolite specific command in a typical
install sequence**. </font> Run it without any arguments to see a usage
message. Run it without the `-q` to get a more verbose, pause-at-every-step,
install mode that allows you to change the defaults etc.
sita@sita-lt:src $ ./gl-easy-install -q git server sitaram
you are upgrading (or installing first-time) to v0.95-38-gb0ce84d
setting up keypair...
Generating public/private rsa key pair.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/sita/.ssh/sitaram.
Your public key has been saved in /home/sita/.ssh/sitaram.pub.
The key fingerprint is:
2a:8e:88:42:36:7e:71:e8:cc:ff:4c:54:64:8e:cf:19 sita@sita-lt.atc.tcs.com
The key's randomart image is:
+--[ RSA 2048]----+
| o |
| = |
| . E |
| + o |
| . .S+ |
| + o ... |
|+ = + .. |
|oo B .o |
|+ o o..o |
+-----------------+
creating gitolite para in ~/.ssh/config...
finding/creating gitolite rc...
installing/upgrading...
Initialized empty Git repository in /home/git/repositories/gitolite-admin.git/
Initialized empty Git repository in /home/git/repositories/testing.git/
Pseudo-terminal will not be allocated because stdin is not a terminal.
fatal: No HEAD commit to compare with (yet)
[master (root-commit) 2f40d4b] start
2 files changed, 13 insertions(+), 0 deletions(-)
create mode 100644 conf/gitolite.conf
create mode 100644 keydir/sitaram.pub
cloning gitolite-admin repo...
Initialized empty Git repository in /home/sita/gitolite-admin/.git/
remote: Counting objects: 6, done.
remote: Compressing objects: 100% (4/4), done.
remote: Total 6 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (6/6), done.
---------------------------------------------------------------
done!
Reminder:
*Your* URL for cloning any repo on this server will be
gitolite:reponame.git
*Other* users you set up will have to use
git@server:reponame.git
If this is your first time installing gitolite, please also:
tail -31 ./gl-easy-install
for next steps.
----
### examine what you have
sita@sita-lt:src $ cd ~/gitolite-admin/
sita@sita-lt:gitolite-admin $ git --no-pager log --stat
commit 2f40d4bb80d424dc39aae5d0973f8c1b2e395666
Author: git <git@sita-lt.atc.tcs.com>
Date: Thu Dec 24 21:39:15 2009 +0530
start
conf/gitolite.conf | 12 ++++++++++++
keydir/sitaram.pub | 1 +
2 files changed, 13 insertions(+), 0 deletions(-)
And that's really all. Add keys to keydir here, edit conf/gitolite.conf as
needed, then add, commit, and push the changes to the server. Try out that
`tail -31 ./gl-easy-install` too :)

View file

@ -4,28 +4,5 @@
# (the GL_ADMINDIR env var would have been set by gl-auth-command) # (the GL_ADMINDIR env var would have been set by gl-auth-command)
GIT_WORK_TREE=$GL_ADMINDIR git checkout -f master GIT_WORK_TREE=$GL_ADMINDIR git checkout -f master
# remove all fragments. otherwise, you get spurious error messages when you
# take away someone's delegation in the main config but the fragment is still
# hanging around. The ones that are valid will get re-created anyway
rm -rf $GL_ADMINDIR/conf/fragments
# collect all the delegated fragments
mkdir $GL_ADMINDIR/conf/fragments
for br in `git for-each-ref --format='%(refname:short)'`
do
# skip master (duh!)
[ "$br" = "master" ] && continue
# all other branches *should* contain a file called <branchname>.conf
# inside conf/fragments; if so copy it
if git show $br:conf/fragments/$br.conf > /dev/null 2>&1
then
git show $br:conf/fragments/$br.conf > $GL_ADMINDIR/conf/fragments/$br.conf
echo "(extracted $br conf; `wc -l < $GL_ADMINDIR/conf/fragments/$br.conf` lines)"
else
echo " ***** ERROR *****"
echo " branch $br does not contain conf/fragments/$br.conf"
fi
done
cd $GL_ADMINDIR cd $GL_ADMINDIR
$GL_BINDIR/gl-compile-conf $GL_BINDIR/gl-compile-conf

View file

@ -127,7 +127,7 @@ if ($cmd eq 'info') {
# git-receive-pack 'reponame.git' # git-receive-pack 'reponame.git'
# including the single quotes # including the single quotes
my ($verb, $repo) = ($cmd =~ /^\s*(git\s+\S+|\S+)\s+'\/?(.*?)(?:.git)?'/); my ($verb, $repo) = ($cmd =~ /^\s*(git\s+\S+|\S+)\s+'\/?(.*?)(?:\.git)?'/);
unless ( $verb and ( $verb =~ $R_COMMANDS or $verb =~ $W_COMMANDS ) and $repo and $repo =~ $REPONAME_PATT ) { unless ( $verb and ( $verb =~ $R_COMMANDS or $verb =~ $W_COMMANDS ) and $repo and $repo =~ $REPONAME_PATT ) {
# if the user is allowed a shell, just run the command # if the user is allowed a shell, just run the command
exec $ENV{SHELL}, "-c", $ENV{SSH_ORIGINAL_COMMAND} if $shell_allowed; exec $ENV{SHELL}, "-c", $ENV{SSH_ORIGINAL_COMMAND} if $shell_allowed;

View file

@ -61,7 +61,7 @@ $Data::Dumper::Sortkeys = sub { return [ reverse sort keys %{$_[0]} ]; };
open STDOUT, ">", "/dev/null" if (@ARGV and shift eq '-q'); open STDOUT, ">", "/dev/null" if (@ARGV and shift eq '-q');
# these are set by the "rc" file # these are set by the "rc" file
our ($GL_ADMINDIR, $GL_CONF, $GL_KEYDIR, $GL_CONF_COMPILED, $REPO_BASE, $REPO_UMASK, $PROJECTS_LIST, $GIT_PATH); our ($GL_ADMINDIR, $GL_CONF, $GL_KEYDIR, $GL_CONF_COMPILED, $REPO_BASE, $REPO_UMASK, $PROJECTS_LIST, $GIT_PATH, $SHELL_USERS);
# and these are set by gitolite.pm # and these are set by gitolite.pm
our ($REPONAME_PATT, $REPOPATT_PATT, $USERNAME_PATT, $AUTH_COMMAND, $AUTH_OPTIONS, $ABRT, $WARN); our ($REPONAME_PATT, $REPOPATT_PATT, $USERNAME_PATT, $AUTH_COMMAND, $AUTH_OPTIONS, $ABRT, $WARN);
@ -209,9 +209,11 @@ sub parse_conf_file
# if no ref is given, this PERM applies to all refs # if no ref is given, this PERM applies to all refs
@refs = qw(refs/.*) unless @refs; @refs = qw(refs/.*) unless @refs;
# fully qualify refs that dont start with "refs/" or "PATH/"; # deprecation warning
map { warn "WARNING: old syntax 'PATH/' found; please use new syntax 'NAME/'\n" if s(^PATH/)(NAME/) } @refs;
# fully qualify refs that dont start with "refs/" or "NAME/";
# prefix them with "refs/heads/" # prefix them with "refs/heads/"
@refs = map { m(^(refs|PATH)/) or s(^)(refs/heads/); $_ } @refs; @refs = map { m(^(refs|NAME)/) or s(^)(refs/heads/); $_ } @refs;
# expand the user list, unless it is just "@all" # expand the user list, unless it is just "@all"
@users = expand_list ( @users ) @users = expand_list ( @users )
@ -267,13 +269,13 @@ sub parse_conf_file
# for 2nd level check, store each "ref, perms" pair in order # for 2nd level check, store each "ref, perms" pair in order
for my $ref (@refs) for my $ref (@refs)
{ {
# checking PATH based restrictions is expensive for # checking NAME based restrictions is expensive for
# the update hook (see the changes to src/hooks/update # the update hook (see the changes to src/hooks/update
# in this commit for why) so we would *very* much like # in this commit for why) so we would *very* much like
# to avoid doing it for the large majority of repos # to avoid doing it for the large majority of repos
# that do *not* use PATH limits. Setting a flag that # that do *not* use NAME limits. Setting a flag that
# can be checked right away will help us do that # can be checked right away will help us do that
$repos{$repo}{PATH_LIMITS} = 1 if $ref =~ /^PATH\//; $repos{$repo}{NAME_LIMITS} = 1 if $ref =~ /^NAME\//;
push @{ $repos{$repo}{$user} }, { $ref => $perms } push @{ $repos{$repo}{$user} }, { $ref => $perms }
unless $rurp_seen{$repo}{$user}{$ref}{$perms}++; unless $rurp_seen{$repo}{$user}{$ref}{$perms}++;
} }
@ -290,6 +292,16 @@ sub parse_conf_file
$repo_config{$repo}{$key} = $value; $repo_config{$repo}{$key} = $value;
} }
} }
# include
elsif (/^include "(.+)"/)
{
my $file = $1;
$file = "$GL_ADMINDIR/conf/$file" unless $file =~ /^\//;
die "$WARN $fragment attempting to include configuration\n" if $fragment ne 'master';
die "$ABRT included file not found: '$file'\n" unless -f $file;
parse_conf_file($file, $fragment);
}
# very simple syntax for the gitweb description of repo; one of: # very simple syntax for the gitweb description of repo; one of:
# reponame = "some description string" # reponame = "some description string"
# reponame "owner name" = "some description string" # reponame "owner name" = "some description string"
@ -483,7 +495,7 @@ for my $pubkey (glob("*"))
print STDERR "WARNING: pubkey $pubkey exists but user $user not in config\n" print STDERR "WARNING: pubkey $pubkey exists but user $user not in config\n"
unless $user_list{$user}; unless $user_list{$user};
$user_list{$user} = 'has pubkey'; $user_list{$user} = 'has pubkey';
if ($groups{'@SHELL'}{$user}) { if ($SHELL_USERS and $SHELL_USERS =~ /(^|\s)$user(\s|$)/) {
print $newkeys_fh "command=\"$AUTH_COMMAND -s $user\",$AUTH_OPTIONS "; print $newkeys_fh "command=\"$AUTH_COMMAND -s $user\",$AUTH_OPTIONS ";
} else { } else {
print $newkeys_fh "command=\"$AUTH_COMMAND $user\",$AUTH_OPTIONS,no-pty "; print $newkeys_fh "command=\"$AUTH_COMMAND $user\",$AUTH_OPTIONS,no-pty ";

View file

@ -302,12 +302,16 @@ copy_gl() {
prompt " ...trying to reuse existing rc" \ prompt " ...trying to reuse existing rc" \
"Oh hey... you already had a '.gitolite.rc' file on the server. "Oh hey... you already had a '.gitolite.rc' file on the server.
Let's see if we can use that instead of the default one..." Let's see if we can use that instead of the default one..."
sort < $tmpgli/.gitolite.rc | perl -ne 'print "$1\n" if /^\s*(\$\w+) *=/' > $tmpgli/glrc.old < $tmpgli/.gitolite.rc perl -ne 'print "$1\n" if /^\s*(\$\w+) *=/' | sort > $tmpgli/glrc.old
sort < conf/example.gitolite.rc | perl -ne 'print "$1\n" if /^\s*(\$\w+) *=/' > $tmpgli/glrc.new < conf/example.gitolite.rc perl -ne 'print "$1\n" if /^\s*(\$\w+) *=/' | sort > $tmpgli/glrc.new
if diff -u $tmpgli/glrc.old $tmpgli/glrc.new comm -13 $tmpgli/glrc.old $tmpgli/glrc.new > $tmpgli/glrc.comm13
if [[ ! -s $tmpgli/glrc.comm13 ]]
then then
[[ $quiet == -q ]] || ${VISUAL:-${EDITOR:-vi}} $tmpgli/.gitolite.rc [[ $quiet == -q ]] || ${VISUAL:-${EDITOR:-vi}} $tmpgli/.gitolite.rc
else else
echo new variables found in rc file:
cat $tmpgli/glrc.comm13
echo
# MANUAL: if you're upgrading, read the instructions below and # MANUAL: if you're upgrading, read the instructions below and
# manually make sure your final ~/.gitolite.rc has both your existing # manually make sure your final ~/.gitolite.rc has both your existing
# customisations as well as any new variables that the new version of # customisations as well as any new variables that the new version of
@ -339,6 +343,8 @@ run_install() {
if ssh -p $port $user@$host cat $GL_ADMINDIR/conf/gitolite.conf &> /dev/null if ssh -p $port $user@$host cat $GL_ADMINDIR/conf/gitolite.conf &> /dev/null
then then
upgrade=1 upgrade=1
ssh -p $port $user@$host cat $GL_ADMINDIR/conf/gitolite.conf 2> /dev/null | grep '@SHELL' &&
prompt "" "$v_at_shell_bwi"
[[ -n $admin_name ]] && echo -e "\n *** WARNING ***: looks like an upgrade... ignoring argument '$admin_name'" [[ -n $admin_name ]] && echo -e "\n *** WARNING ***: looks like an upgrade... ignoring argument '$admin_name'"
else else
[[ -z $admin_name ]] && die " *** ERROR ***: doesn't look like an upgrade, so I need a name for the admin" [[ -z $admin_name ]] && die " *** ERROR ***: doesn't look like an upgrade, so I need a name for the admin"
@ -361,7 +367,6 @@ run_install() {
# MANUAL: setup the initial config file. Edit $GL_ADMINDIR/conf/gitolite.conf # MANUAL: setup the initial config file. Edit $GL_ADMINDIR/conf/gitolite.conf
# and add at least the following lines to it: # and add at least the following lines to it:
# @SHELL = sitaram
# repo gitolite-admin # repo gitolite-admin
# RW+ = sitaram # RW+ = sitaram
@ -369,8 +374,6 @@ initial_conf_key() {
echo "#gitolite conf echo "#gitolite conf
# please see conf/example.conf for details on syntax and features # please see conf/example.conf for details on syntax and features
@SHELL = $admin_name
repo gitolite-admin repo gitolite-admin
RW+ = $admin_name RW+ = $admin_name
@ -401,7 +404,6 @@ setup_pta() {
# Substitute $GL_ADMINDIR and $REPO_BASE appropriately. Note there is no # Substitute $GL_ADMINDIR and $REPO_BASE appropriately. Note there is no
# space around the "=" in the second and third lines. # space around the "=" in the second and third lines.
git ls-remote gitolite:gitolite-admin
echo "cd $REPO_BASE/gitolite-admin.git echo "cd $REPO_BASE/gitolite-admin.git
GIT_WORK_TREE=$GL_ADMINDIR git add conf/gitolite.conf keydir GIT_WORK_TREE=$GL_ADMINDIR git add conf/gitolite.conf keydir
GIT_WORK_TREE=$GL_ADMINDIR git diff --cached --quiet || GIT_WORK_TREE=$GL_ADMINDIR git commit -am start GIT_WORK_TREE=$GL_ADMINDIR git diff --cached --quiet || GIT_WORK_TREE=$GL_ADMINDIR git commit -am start
@ -544,6 +546,17 @@ next set of command outputs coming up. They're only relevant for a manual
install, not this one... install, not this one...
" "
v_at_shell_bwi="
you are using the @SHELL feature in your gitolite config. This feature has
now changed in a backward incompatible way; see doc/6-ssh-troubleshooting.mkd
for information on migrating this to the new syntax.
DO NOT hit enter unless you have understood that information and properly
migrated your setup, or you are sure you have shell access to the server
through some other means than the $admin_name key.
"
v_done=" v_done="
done! done!

View file

@ -78,12 +78,12 @@ push @allowed_refs, @ { $repos{$ENV{GL_REPO}}{'@all'} || [] };
# prepare the list of refs to be checked # prepare the list of refs to be checked
# previously, we just checked $ref -- the ref being updated, which is passed # previously, we just checked $ref -- the ref being updated, which is passed
# to us by git (see man githooks). Now we also have to treat each PATH being # to us by git (see man githooks). Now we also have to treat each NAME being
# updated as a potential "ref" and check that, if PATH-based restrictions have # updated as a potential "ref" and check that, if NAME-based restrictions have
# been specified # been specified
my @refs = ($ref); # the first ref to check is the real one my @refs = ($ref); # the first ref to check is the real one
if (exists $repos{$ENV{GL_REPO}}{PATH_LIMITS}) { if (exists $repos{$ENV{GL_REPO}}{NAME_LIMITS}) {
# this is special to git -- the hash of an empty tree # this is special to git -- the hash of an empty tree
my $empty='4b825dc642cb6eb9a060e54bf8d69288fbee4904'; my $empty='4b825dc642cb6eb9a060e54bf8d69288fbee4904';
# well they're not really "trees" but $empty is indeed the empty tree so # well they're not really "trees" but $empty is indeed the empty tree so
@ -91,7 +91,7 @@ if (exists $repos{$ENV{GL_REPO}}{PATH_LIMITS}) {
# diff' only wants trees # diff' only wants trees
my $oldtree = $oldsha eq '0' x 40 ? $empty : $oldsha; my $oldtree = $oldsha eq '0' x 40 ? $empty : $oldsha;
my $newtree = $newsha eq '0' x 40 ? $empty : $newsha; my $newtree = $newsha eq '0' x 40 ? $empty : $newsha;
push @refs, map { chomp; s/^/PATH\//; $_; } `git diff --name-only $oldtree $newtree`; push @refs, map { chomp; s/^/NAME\//; $_; } `git diff --name-only $oldtree $newtree`;
} }
my $refex = ''; my $refex = '';
@ -113,7 +113,7 @@ sub check_ref {
for my $ar (@allowed_refs) { for my $ar (@allowed_refs) {
$refex = (keys %$ar)[0]; $refex = (keys %$ar)[0];
# refex? sure -- a regex to match a ref against :) # refex? sure -- a regex to match a ref against :)
next unless $ref =~ /$refex/; next unless $ref =~ /^$refex/;
die "$perm $ref $reported_repo $ENV{GL_USER} DENIED by $refex\n" if $ar->{$refex} eq '-'; die "$perm $ref $reported_repo $ENV{GL_USER} DENIED by $refex\n" if $ar->{$refex} eq '-';
# as far as *this* ref is concerned we're ok # as far as *this* ref is concerned we're ok
@ -124,7 +124,7 @@ sub check_ref {
# and in this version, we have many "refs" to check. The one we print in the # and in this version, we have many "refs" to check. The one we print in the
# log is the *first* one (which is a *real* ref, like refs/heads/master), # log is the *first* one (which is a *real* ref, like refs/heads/master),
# while all the rest (if they exist) are like PATH/something. So we do the # while all the rest (if they exist) are like NAME/something. So we do the
# first one separately to capture it, then run the rest (if any) # first one separately to capture it, then run the rest (if any)
my $log_refex = check_ref(shift @refs); my $log_refex = check_ref(shift @refs);
check_ref($_) for @refs; check_ref($_) for @refs;