diff options
Diffstat (limited to 'src')
-rwxr-xr-x | src/00-easy-install.sh | 362 | ||||
-rwxr-xr-x | src/gl-auth-command | 5 | ||||
-rwxr-xr-x | src/gl-compile-conf | 5 | ||||
-rwxr-xr-x | src/install.pl | 16 |
4 files changed, 381 insertions, 7 deletions
diff --git a/src/00-easy-install.sh b/src/00-easy-install.sh new file mode 100755 index 0000000..a9d8700 --- /dev/null +++ b/src/00-easy-install.sh @@ -0,0 +1,362 @@ +#!/bin/bash + +# easy install for gitolite + +# you run this on the client side, and it takes care of all the server side +# work. You don't have to do anything on the server side directly + +# to do a manual install (since I have tested this only on Linux), open this +# script in a nice, syntax coloring, text editor and follow the instructions +# prefixed by the word "MANUAL" in the comments below :-) + +# run without any arguments for "usage" info + +# important setting: bail on any errors (else we have to check every single +# command!) +set -e + +die() { echo "$@"; echo; echo "run $0 again without any arguments for help and tips"; exit 1; } +prompt() { + echo + echo + echo ------------------------------------------------------------------------ + echo " $1" + echo + read -p '...press enter to continue or Ctrl-C to bail out' +} +usage() { + cat <<EOFU +Usage: $0 user host port admin_name + - "user" is the username on the server where you will be installing gitolite + - "host" is that server's hostname (or IP address is also fine) + - "port" is optional + - "admin_name" is *your* name as you want it to appear in the eventual + gitolite config file + +Example usage: $0 git my.git.server sitaram + +Output: + - a proper gitolite admin repo in $HOME/gitolite-admin + +Notes: + - "user" and "admin_name" must be simple names -- no special characters etc + please (only alphanumerics, dot, hyphen, underscore) + - traditionally, the "user" is "git", but it can be anything you want + - "admin_name" should be your name, for clarity, or whoever will be the + gitolite admin + +Pre-requisites: + - you must run this from the gitolite working tree top level directory. + This means you run this as "src/00-easy-install.sh" + - you must already have pubkey based access to user@host. If you currently + only have password access, use "ssh-copy-id" or something. Somehow get to + the point where you can type "ssh user@host" and get a command line. Run + this program only after that is done + +Errors: + - if you get a "pubkey [...filename...] exists" error, it is either leftover + from a previous, failed, run, or a genuine file you need. Decide which it + is, and remove it and retry, or use a different "admin_name", respectively. + +EOFU + exit 1; +} + +# ---------------------------------------------------------------------- +# basic sanity / argument checks +# ---------------------------------------------------------------------- + +# MANUAL: this *must* be run as "src/00-easy-install.sh", not by cd-ing to src +# and then running "./00-easy-install.sh" + +[[ $0 =~ ^src/00-easy-install.sh$ ]] || +{ + echo "please cd to the gitolite repo top level directory and run this as + 'src/00-easy-install.sh'" + exit 1; +} + +# MANUAL: (info) we'll use "git" as the user, "server" as the host, and +# "sitaram" as the admin_name in example commands shown below, if any + +[[ -z $3 ]] && usage +user=$1 +host=$2 +admin_name=$3 +# but if the 3rd arg is a number, that's a port number, and the 4th arg is the +# admin_name +port=22 +[[ $3 =~ ^[0-9]+$ ]] && { + port=$3 + [[ -z $4 ]] && usage + admin_name=$4 +} + +[[ "$user" =~ [^a-zA-Z0-9._-] ]] && die "user '$user' invalid" +[[ "$admin_name" =~ [^a-zA-Z0-9._-] ]] && die "admin_name '$admin_name' invalid" + +# MANUAL: make sure you're in the gitolite directory, at the top level. +# The following files should all be visible: + +ls src/gl-auth-command \ + src/gl-compile-conf \ + src/install.pl \ + src/update-hook.pl \ + conf/example.conf \ + conf/example.gitolite.rc >/dev/null || + die "cant find at least some files in gitolite sources/config; aborting" + +# MANUAL: make sure you have password-less (pubkey) auth on the server. That +# is, running "ssh git@server" should log in straight away, without asking for +# a password + +ssh -p $port -o PasswordAuthentication=no $user@$host true || + die "pubkey access didn't work; please set it up using 'ssh-copy-id' or something" + +# MANUAL: make sure there's no "gitolite-admin" directory in $HOME (actually +# for the manual flow this doesn't matter so much!) + +[[ -d $HOME/gitolite-admin ]] && + die "please delete or move aside the \$HOME/gitolite-admin directory" + +# MANUAL: create a new key for you as a "gitolite user" (as opposed to you as +# the "gitolite admin" who needs to login to the server and get a command +# line). For example, "ssh-keygen -t rsa ~/.ssh/sitaram"; this would create +# two files in ~/.ssh (sitaram and sitaram.pub) + +prompt "the next command will create a new keypair for your gitolite access + + The pubkey will be $HOME/.ssh/$admin_name.pub. You will have to + choose a passphrase or hit enter for none. I recommend not having a + passphrase for now, and adding one with 'ssh-keygen -p' *as soon as* + all the setup is done and you've successfully cloned and pushed the + gitolite-admin repo. + + After that, I suggest you (1) install 'keychain' or something + similar, and (2) add the following command to your bashrc (since + this is a non-default key) + + ssh-add \$HOME/.ssh/$admin_name + + This makes using passphrases very convenient." + +if [[ -f $HOME/.ssh/$admin_name.pub ]] +then + prompt "Hmmm... pubkey $HOME/.ssh/$admin_name.pub exists; should I just re-use it? + Be sure you remember the passphrase, if you gave one when you created it!" +else + ssh-keygen -t rsa -f $HOME/.ssh/$admin_name || die "ssh-keygen failed for some reason..." +fi + +# MANUAL: copy the pubkey created to the server, say to /tmp. This would be +# "scp ~/.ssh/sitaram.pub git@server:/tmp" (the script does this at a later +# stage, you do it now for convenience). Note: only the pubkey (sitaram.pub). +# Do NOT copy the ~/.ssh/sitaram file -- that is a private key! + +# MANUAL: if you're running ssh-agent (see if you have an environment variable +# called SSH_AGENT_PID in your "env"), you should add this new key. The +# command is "ssh-add ~/.ssh/sitaram" + +if ssh-add -l &>/dev/null +then + prompt "you're running ssh-agent. We'll try and do an ssh-add of the + private key we just created, otherwise this key won't get picked up. If + you specified a passphrase in the previous step, you'll get asked for one + now -- type in the same one." + + ssh-add $HOME/.ssh/$admin_name +fi + +# MANUAL: you now need to add some lines to the end of your ~/.ssh/config +# file. If the file doesn't exist, create it. Make sure the file is "chmod +# 644". + +# The lines to be included look like this: + +# host gitolite +# user git +# hostname server +# port 22 +# identityfile ~/.ssh/sitaram + +echo " +host gitolite + user $user + hostname $host + port $port + identityfile ~/.ssh/$admin_name" > $HOME/.ssh/.gl-stanza + +if grep 'host *gitolite' $HOME/.ssh/config &>/dev/null +then + prompt "your \$HOME/.ssh/config already has settings for gitolite. I will + assume they're correct, but if they're not, please edit that file, delete + that paragraph (that line and the following few lines), Ctrl-C, and rerun. + + In case you want to check right now (from another terminal) if they're + correct, here's what they are *supposed* to look like: +$(cat ~/.ssh/.gl-stanza)" + +else + prompt "creating settings for your gitolite access in $HOME/.ssh/config; + these are the lines that will be appended to your ~/.ssh/config: +$(cat ~/.ssh/.gl-stanza)" + + cat $HOME/.ssh/.gl-stanza >> $HOME/.ssh/config + # if the file didn't exist at all, it might have the wrong permissions + chmod 644 $HOME/.ssh/config +fi +rm $HOME/.ssh/.gl-stanza + +# ---------------------------------------------------------------------- +# client side stuff almost done; server side now +# ---------------------------------------------------------------------- + +# MANUAL: copy the gitolite directories "src", "conf", and "doc" to the +# server, to a directory called (for example) "gitolite-install". You may +# have to create the directory first. + +ssh -p $port $user@$host mkdir -p gitolite-install +rsync -e "ssh -p $port" -a src conf doc $user@$host:gitolite-install/ + +# MANUAL: now log on to the server (ssh git@server) and get a command line. +# This step is for your convenience; the script does it all from the client +# side but that may be too much typing for manual use ;-) + +# MANUAL: cd to the "gitolite-install" directory where the sources are. Then +# copy conf/example.gitolite.rc as ~/.gitolite.rc and edit it if you wish to +# change any paths. Make a note of the GL_ADMINDIR and REPO_BASE paths; you +# will need them later + +prompt "the gitolite rc file needs to be edited by hand. The defaults + are sensible, so if you wish, you can just exit the editor. + + Otherwise, make any changes you wish and save it. Read the comments to + understand what is what -- the rc file's documentation is inline. + + Please remember this file will actually be copied to the server, and that + all the paths etc. represent paths on the server!" + +# lets try and get the file from there first +if scp -P $port $user@$host:.gitolite.rc . +then + prompt "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..." + sort < .gitolite.rc | perl -ne 'print "$1\n" if /^(\$\w+) *=/' > glrc.old + sort < conf/example.gitolite.rc | perl -ne 'print "$1\n" if /^(\$\w+) *=/' > glrc.new + if diff -u glrc.old glrc.new + then + ${VISUAL:-${EDITOR:-vi}} .gitolite.rc + else + prompt " looks like you're upgrading! I'm going to run your editor + with *both* the old and the new files (in that order), so you can add + in the lines pertaining to the variables shown with a '+' sign in the + above diff. This is necessary; please dont skip this + + [It's upto you to figure out how your editor handles 2 filename + arguments, switch between them, copy lines, etc ;-)]" + ${VISUAL:-${EDITOR:-vi}} .gitolite.rc conf/example.gitolite.rc + fi +else + cp conf/example.gitolite.rc .gitolite.rc + ${VISUAL:-${EDITOR:-vi}} .gitolite.rc +fi + +# copy the rc across +scp -P $port .gitolite.rc $user@$host: + +prompt "ignore any 'please edit this file' or 'run this command' type + lines in the next set of command outputs coming up. They're only relevant + for a manual install, not this one..." + +# extract the GL_ADMINDIR and REPO_BASE locations +GL_ADMINDIR=$(ssh -p $port $user@$host "perl -e 'do \".gitolite.rc\"; print \$GL_ADMINDIR'") +REPO_BASE=$( ssh -p $port $user@$host "perl -e 'do \".gitolite.rc\"; print \$REPO_BASE'") + +# MANUAL: still in the "gitolite-install" directory? Good. Run +# "src/install.pl" + +ssh -p $port $user@$host "cd gitolite-install; src/install.pl" + +# MANUAL: setup the initial config file. Edit $GL_ADMINDIR/conf/gitolite.conf +# and add at least the following lines to it: + +# repo gitolite-admin +# RW+ = sitaram + +echo "#gitolite conf +#please see conf/example.conf for details on syntax and features + +repo gitolite-admin + RW+ = $admin_name + +repo testing + RW+ = @all + +" > gitolite.conf + +# send the config and the key to the remote +scp -P $port gitolite.conf $user@$host:$GL_ADMINDIR/conf/ + +scp -P $port $HOME/.ssh/$admin_name.pub $user@$host:$GL_ADMINDIR/keydir + +# MANUAL: cd to $GL_ADMINDIR and run "src/gl-compile-conf" + +ssh -p $port $user@$host "cd $GL_ADMINDIR; src/gl-compile-conf" + +# ---------------------------------------------------------------------- +# hey lets go the whole hog on this; setup push-to-admin! +# ---------------------------------------------------------------------- + +# MANUAL: make the first commit in the admin repo. This is a little more +# complex, so read carefully and substitute the correct paths. What you have +# to do is: + +# cd $REPO_BASE/gitolite-admin.git +# GIT_WORK_TREE=$GL_ADMINDIR git add conf/gitolite.conf keydir +# GIT_WORK_TREE=$GL_ADMINDIR git commit -am start + +# Substitute $GL_ADMINDIR and $REPO_BASE appropriately. Note there is no +# space around the "=" in the second and third lines. + +echo "cd $REPO_BASE/gitolite-admin.git +GIT_WORK_TREE=$GL_ADMINDIR git add conf/gitolite.conf keydir +GIT_WORK_TREE=$GL_ADMINDIR git commit -am start --allow-empty +" | ssh -p $port $user@$host + +# MANUAL: now that the admin repo is created, you have to set the hooks +# properly. The install program does this. So cd back to the +# "gitolite-install" directory and run "src/install.pl" + +ssh -p $port $user@$host "cd gitolite-install; src/install.pl" + +prompt "now we will clone the gitolite-admin repo to your workstation + and see if it all hangs together. We'll do this in your \$HOME for now, + and you can move it elsewhere later if you wish to." + +# MANUAL: you're done! Log out of the server, come back to your workstation, +# and clone the admin repo using "git clone gitolite:gitolite-admin.git"! + +cd $HOME +git clone gitolite:gitolite-admin.git + +# MANUAL: be sure to read the message below; this applies to you too... + +echo +echo +echo ------------------------------------------------------------------------ +echo "Cool -- we're done. Now you can edit the config file (currently +in ~/gitolite-admin/conf/gitolite.conf) to add more repos, users, etc. +When done, 'git add' the changed files, 'git commit' and 'git push'. + +Read the comments in conf/example.conf for information about the config +file format -- like the rc file, this also has inline documentation. + +Your URL for cloning any repo on this server will be + + gitolite:reponame.git + +However, any other users you set up will have to use + + $user@$host:reponame.git + +unless they also create similar settings in their '.ssh/config' file." diff --git a/src/gl-auth-command b/src/gl-auth-command index 62573d4..8201403 100755 --- a/src/gl-auth-command +++ b/src/gl-auth-command @@ -24,13 +24,16 @@ use warnings; # ---------------------------------------------------------------------------- -our ($GL_LOGT, $GL_CONF_COMPILED, $REPO_BASE); +our ($GL_LOGT, $GL_CONF_COMPILED, $REPO_BASE, $GIT_PATH); our %repos; my $glrc = $ENV{HOME} . "/.gitolite.rc"; die "parse $glrc failed: " . ($! or $@) unless do $glrc; die "parse $GL_CONF_COMPILED failed: " . ($! or $@) unless do $GL_CONF_COMPILED; +# add a custom path for git binaries, if specified +$ENV{PATH} .= ":$GIT_PATH" if $GIT_PATH; + # ---------------------------------------------------------------------------- # definitions specific to this program # ---------------------------------------------------------------------------- diff --git a/src/gl-compile-conf b/src/gl-compile-conf index ad50c4a..f51f97a 100755 --- a/src/gl-compile-conf +++ b/src/gl-compile-conf @@ -47,7 +47,7 @@ $Data::Dumper::Indent = 1; # common definitions # ---------------------------------------------------------------------------- -our ($GL_ADMINDIR, $GL_CONF, $GL_KEYDIR, $GL_CONF_COMPILED, $REPO_BASE, $REPO_UMASK, $PROJECTS_LIST); +our ($GL_ADMINDIR, $GL_CONF, $GL_KEYDIR, $GL_CONF_COMPILED, $REPO_BASE, $REPO_UMASK, $PROJECTS_LIST, $GIT_PATH); # now that this thing *may* be run via "push to admin", any errors have to # grab the admin's ATTENTION so he won't miss them among the other messages a @@ -57,6 +57,9 @@ my $ATTN = "\n\t\t***** ERROR *****\n "; my $glrc = $ENV{HOME} . "/.gitolite.rc"; die "$ATTN parse $glrc failed: " . ($! or $@) unless do $glrc; +# add a custom path for git binaries, if specified +$ENV{PATH} .= ":$GIT_PATH" if $GIT_PATH; + # ---------------------------------------------------------------------------- # definitions specific to this program # ---------------------------------------------------------------------------- diff --git a/src/install.pl b/src/install.pl index 017854f..f6e4142 100755 --- a/src/install.pl +++ b/src/install.pl @@ -3,7 +3,7 @@ use strict; use warnings; -our ($REPO_BASE, $GL_ADMINDIR, $GL_CONF); +our ($REPO_BASE, $GL_ADMINDIR, $GL_CONF, $GIT_PATH); # wrapper around mkdir; it's not an error if the directory exists, but it is # an error if it doesn't exist and we can't create it @@ -33,6 +33,9 @@ unless (-f $glrc) { # ok now $glrc exists; read it to get the other paths die "parse $glrc failed: " . ($! or $@) unless do $glrc; +# add a custom path for git binaries, if specified +$ENV{PATH} .= ":$GIT_PATH" if $GIT_PATH; + # mkdir $REPO_BASE, $GL_ADMINDIR if they don't already exist my $repo_base_abs = ( $REPO_BASE =~ m(^/) ? $REPO_BASE : "$ENV{HOME}/$REPO_BASE" ); wrap_mkdir($repo_base_abs); @@ -66,7 +69,10 @@ for my $repo (`find . -type d -name "*.git"`) { } # oh and one of those repos is a bit more special and has an extra hook :) -system("cp $GL_ADMINDIR/src/pta-hook.sh gitolite-admin.git/hooks/post-update"); -system("perl", "-i", "-p", "-e", "s(export GL_ADMINDIR=.*)(export GL_ADMINDIR=$GL_ADMINDIR)", - "gitolite-admin.git/hooks/post-update"); -chmod 0755, "gitolite-admin.git/hooks/post-update"; +if ( -d "gitolite-admin.git/hooks" ) { + print STDERR "copying post-update hook to gitolite-admin repo...\n"; + system("cp -v $GL_ADMINDIR/src/pta-hook.sh gitolite-admin.git/hooks/post-update"); + system("perl", "-i", "-p", "-e", "s(export GL_ADMINDIR=.*)(export GL_ADMINDIR=$GL_ADMINDIR)", + "gitolite-admin.git/hooks/post-update"); + chmod 0755, "gitolite-admin.git/hooks/post-update"; +} |