diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/gitolite.pm | 32 | ||||
-rwxr-xr-x | src/gl-admin-push | 13 | ||||
-rwxr-xr-x | src/gl-compile-conf | 4 | ||||
-rwxr-xr-x | src/gl-conf-convert | 4 | ||||
-rwxr-xr-x | src/gl-dryrun | 8 | ||||
-rwxr-xr-x | src/gl-install | 102 | ||||
-rwxr-xr-x | src/gl-mirror-push | 1 | ||||
-rwxr-xr-x | src/gl-mirror-shell | 14 | ||||
-rwxr-xr-x | src/gl-setup | 81 | ||||
-rwxr-xr-x | src/gl-system-install | 209 | ||||
-rwxr-xr-x | src/gl-tool | 2 | ||||
-rwxr-xr-x | src/sshkeys-lint | 5 |
12 files changed, 279 insertions, 196 deletions
diff --git a/src/gitolite.pm b/src/gitolite.pm index ca66107..37f3977 100644 --- a/src/gitolite.pm +++ b/src/gitolite.pm @@ -27,6 +27,7 @@ use Exporter 'import'; slurp special_cmd try_adc + wrap_mkdir wrap_chdir wrap_open wrap_print @@ -105,6 +106,17 @@ our %one_git_config; # ditto for %git_configs # convenience subs # ---------------------------------------------------------------------------- +sub wrap_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 + my $dir = shift; + my $perm = shift; # optional + return if -d $dir; + mkdir($dir) or die "mkdir $dir failed: $!\n"; + chmod $perm, $dir if $perm; +} + sub wrap_chdir { chdir($_[0]) or die "$ABRT chdir $_[0] failed: $! at ", (caller)[1], " line ", (caller)[2], "\n"; } @@ -125,6 +137,19 @@ sub wrap_print { chmod $oldmode, $file if $oldmode; } +sub wrap_system { + system(@_); + + # straight from 'perldoc -f system' (sans the coredump part) + if ( $? == -1 ) { + print STDERR "failed to execute: $!\n"; + } elsif ( $? & 127 ) { + printf STDERR "child died with signal %d\n", ( $? & 127 ); + } else { + printf STDERR "child exited with value %d\n", $? >> 8; + } +} + sub slurp { local $/ = undef; my $fh = wrap_open("<", $_[0]); @@ -169,7 +194,9 @@ sub dos2unix { sub log_it { my ($ip, $logmsg); - open my $log_fh, ">>", $ENV{GL_LOG} or die "open log failed: $!\n"; + open my $log_fh, ">>", $ENV{GL_LOG} or die + "open log failed: $!\n" . + "attempting to log: " . ( $_[0] || '(nothing)' ) . "\n"; # first space sep field is client ip, per "man ssh" ($ip = $ENV{SSH_CONNECTION} || '(no-IP)') =~ s/ .*//; # the first part of logmsg is the actual command used; it's either passed @@ -467,6 +494,7 @@ sub setup_git_configs next if $key =~ /^gitolite-options\./; if ($value ne "") { $value =~ s/^['"](.*)["']$/$1/; + $value =~ s/%GL_REPO/$repo/; system("git", "config", $key, $value); } else { system("git", "config", "--unset-all", $key); @@ -562,7 +590,7 @@ sub setup_gitweb_access system("git config --remove-section gitweb 2>/dev/null"); } - return ($desc or can_read($repo, 'gitweb')); + return (can_read($repo, 'gitweb') or $desc); # this return value is used by the caller to write to projects.list } diff --git a/src/gl-admin-push b/src/gl-admin-push index 3fd0214..cd71137 100755 --- a/src/gl-admin-push +++ b/src/gl-admin-push @@ -1,6 +1,15 @@ #!/bin/sh die() { echo "$@" >&2; exit 1; } +if [ "$1" = "-h" ] +then + echo Usage: + echo " gl-admin-push [any options applicable to 'git push' command]" + echo + echo "Please see the 'gl-admin-push: ...' section in doc/tips-notes.mkd (Online at" + echo " http://sitaramc.github.com/gitolite/adminpush.html)" + exit 1 +fi # ---------- @@ -9,7 +18,7 @@ die() { echo "$@" >&2; exit 1; } GL_BINDIR=` perl -ne 'print($1), exit if /^command="(.+?)\/gl-(time|auth-command) /' < $HOME/.ssh/authorized_keys` # GL_BINDIR still not known? we have a problem... [ -z "$GL_BINDIR" ] && { - cat <<EOF2 + echo " Unable to determine correct path for gitolite scripts from the authkeys file. @@ -21,7 +30,7 @@ this command. For example (if you followed doc/http-backend.mkd precisely): GL_BINDIR=/var/www/gitolite-home/bin $0 $@ -EOF2 +" exit 1 } diff --git a/src/gl-compile-conf b/src/gl-compile-conf index 594d54c..4c296e6 100755 --- a/src/gl-compile-conf +++ b/src/gl-compile-conf @@ -175,9 +175,9 @@ sub parse_conf_line @refs = qw(refs/.*) unless @refs; # deprecation warning map { print STDERR "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/"; + # fully qualify refs that dont start with "refs/" or "NAME/" or "VREF/"; # prefix them with "refs/heads/" - @refs = map { m(^(refs|NAME)/) or s(^)(refs/heads/); $_ } @refs; + @refs = map { m(^(refs|NAME|VREF)/) or s(^)(refs/heads/); $_ } @refs; @refs = map { s(/USER/)(/\$gl_user/); $_ } @refs; # expand the user list, unless it is just "@all" diff --git a/src/gl-conf-convert b/src/gl-conf-convert index 1faca4f..7b0bfee 100755 --- a/src/gl-conf-convert +++ b/src/gl-conf-convert @@ -9,6 +9,10 @@ use strict; use warnings; +if (not @ARGV and -t or $ARGV[0] eq '-h') { + print "Usage:\n gl-conf-convert < gitosis.conf > gitolite.conf\n(please the documentation for more)\n"; + exit 1; +} my @comments = (); my $groupname; diff --git a/src/gl-dryrun b/src/gl-dryrun index 2ebd198..5943433 100755 --- a/src/gl-dryrun +++ b/src/gl-dryrun @@ -11,7 +11,7 @@ cat <<EOFU This is a quick hack. It is not "production quality". Resist the temptation to turn this into an update.secondary hook and put it on the server. I WILL NOT BE RESPONSIBLE FOR ANY PROBLEMS IF YOU DO THAT. (Even more so if you use -'git checkout $3' *without* setting GIT_INDEX_FILE to something temporary, and +'git checkout' *without* setting GIT_INDEX_FILE to something temporary, and eventually realise that *deleted* files don't stay deleted...! And if you didn't understand that, all the more reason not to do it). @@ -35,6 +35,8 @@ EOFU exit 1; } +[ "$1" = "-h" ] && usage + [ -n "$1" ] || die "need an admin username" admin="$1"; shift @@ -69,7 +71,7 @@ $GL_CONF_COMPILED="$GL_ADMINDIR/conf/gitolite.conf-compiled.pm"; $GL_WILDREPOS = 1; $PROJECTS_LIST = $ENV{PWD} . "/projects.list"; $REPO_UMASK = 0077; -$GL_BIG_CONFIG = 0; +$GL_BIG_CONFIG = 1; $GL_NO_DAEMON_NO_GITWEB = 1; $GIT_PATH=""; $GL_GITCONFIG_KEYS = ".*"; @@ -86,7 +88,7 @@ EOF # now compile it echo compiling... -$GL_BINDIR/gl-compile-conf +$GL_BINDIR/gl-compile-conf || die "compile failed; aborting rest of run" echo echo "checking if $admin has push rights..." diff --git a/src/gl-install b/src/gl-install index de7aefd..ac9e84e 100755 --- a/src/gl-install +++ b/src/gl-install @@ -2,6 +2,8 @@ # INTERNAL COMMAND. NOT MEANT TO BE RUN BY THE USER DIRECTLY. +# sets up REPO_BASE, GL_ADMINDIR. Symlinks hooks + use strict; use warnings; @@ -10,108 +12,52 @@ use warnings; # ---------------------------------------------------------------------------- BEGIN { - die "ENV GL_RC not set\n" unless $ENV{GL_RC}; + die "ENV GL_RC not set\n" unless $ENV{GL_RC}; die "ENV GL_BINDIR not set\n" unless $ENV{GL_BINDIR}; } use lib $ENV{GL_BINDIR}; + use gitolite_rc; +use gitolite_env; use gitolite; -# ---------------------------------------------------------------------------- -# start... -# ---------------------------------------------------------------------------- - -# setup quiet mode if asked; please do not use this when running manually -open STDOUT, ">", "/dev/null" if (@ARGV and shift eq '-q'); - -# 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 -sub wrap_mkdir -{ - my $dir = shift; - my $perm = shift; # optional - if ( -d $dir ) { - print "$dir already exists\n"; - return; - } - mkdir($dir) or die "mkdir $dir failed: $!\n"; - chmod $perm, $dir if $perm; - print "created $dir\n"; -} - -unless ($ENV{GL_RC}) { - # doesn't exist. Copy it across, tell user to edit it and come back - my $glrc = $ENV{HOME} . "/.gitolite.rc"; - if ($GL_PACKAGE_CONF) { - system("cp $GL_PACKAGE_CONF/example.gitolite.rc $glrc"); - } else { - system("cp $ENV{GL_BINDIR}/../conf/example.gitolite.rc $glrc"); - } - print "created $glrc\n"; - print "please edit it, change the paths if you wish to, and RERUN THIS SCRIPT\n"; - exit; -} - -# add a custom path for git binaries, if specified -$ENV{PATH} .= ":$GIT_PATH" if $GIT_PATH; - -# set the umask before creating any files/directories -umask($REPO_UMASK); +setup_environment(); # mkdir $REPO_BASE, $GL_ADMINDIR if they don't already exist wrap_mkdir($REPO_BASE); -wrap_mkdir($GL_ADMINDIR, 0700); +wrap_mkdir( $GL_ADMINDIR, 0700 ); + # mkdir $GL_ADMINDIR's subdirs -for my $dir (qw(conf doc keydir logs src hooks hooks/common hooks/gitolite-admin)) { - # some of them will stay empty; too lazy to fix right now ;-) - wrap_mkdir("$GL_ADMINDIR/$dir", 0700); +for my $dir (qw(conf keydir logs hooks hooks/common hooks/gitolite-admin)) { + wrap_mkdir( "$GL_ADMINDIR/$dir", 0700 ); } -# "src" and "doc" will be overwritten on each install, but not conf -if ($GL_PACKAGE_HOOKS) { - system("cp -R -p $GL_PACKAGE_HOOKS $GL_ADMINDIR"); -} else { - system("cp -R -p $ENV{GL_BINDIR}/../src $ENV{GL_BINDIR}/../doc $ENV{GL_BINDIR}/../hooks $GL_ADMINDIR"); - system("cp $ENV{GL_BINDIR}/../conf/VERSION $GL_ADMINDIR/conf"); -} +# hooks must be propagated to all the repos in case they changed -unless (-f $GL_CONF or $GL_PACKAGE_CONF) { - print <<EOF; - please do the following: - 1. create and edit $GL_CONF to contain something like this: - repo gitolite-admin - RW+ = yourname - 2. copy "yourname.pub" to $GL_ADMINDIR/keydir - 3. run this command - $GL_ADMINDIR/src/gl-compile-conf -EOF -} +# See http://sitaramc.github.com/gitolite/hook_prop.html if you're not sure +# what is happening here, especially the picture toward the end. -# finally, hooks must be propagated to all the repos in case they changed +# all repos, all hooks chdir($REPO_BASE) or die "chdir $REPO_BASE failed: $!\n"; for my $repo (`find . -type d -name "*.git" -prune`) { - chomp ($repo); - # propagate our own, plus any local admin-defined, hooks - ln_sf("$GL_ADMINDIR/hooks/common", "*", "$repo/hooks"); - # in case of package install, GL_ADMINDIR is no longer the top cop; - # override with the package hooks - ln_sf("$GL_PACKAGE_HOOKS/common", "*", "$repo/hooks") if $GL_PACKAGE_HOOKS; + chomp($repo); + # propagate user hooks + ln_sf( "$GL_ADMINDIR/hooks/common", "*", "$repo/hooks" ); + # propagate package hooks, overriding user hooks + ln_sf( "$GL_PACKAGE_HOOKS/common", "*", "$repo/hooks" ); chmod 0755, "$repo/hooks/update"; } -# oh and one of those repos is a bit more special and has an extra hook :) +# (special!) gitolite-admin repo, post-update hook, package hook only if ( -d "gitolite-admin.git/hooks" ) { - print "copying post-update hook to gitolite-admin repo...\n"; - unlink "gitolite-admin.git/hooks/post-update"; - symlink "$GL_ADMINDIR/hooks/gitolite-admin/post-update", "gitolite-admin.git/hooks/post-update" - or die "could not symlink post-update hook\n"; - # ditto... (see previous block) - ln_sf("$GL_PACKAGE_HOOKS/gitolite-admin", "post-update", "gitolite-admin.git/hooks") if $GL_PACKAGE_HOOKS; + ln_sf( "$GL_PACKAGE_HOOKS/gitolite-admin", "post-update", "gitolite-admin.git/hooks" ); chmod 0755, "gitolite-admin.git/hooks/post-update"; } -# fixup program renames +# deal with old program names... +# not needed for RPM/DEB type systems since they take care of it themselves +# but people upgrading might appreciate this; not sure how useful it is though for my $oldname (qw(pta-hook.sh conf-convert.pl 00-easy-install.sh gl-easy-install 99-emergency-addkey.sh gl-emergency-addkey install.pl update-hook.pl hooks/update ga-post-update-hook VERSION)) { unlink "$GL_ADMINDIR/src/$oldname"; unlink "$ENV{HOME}/gitolite-install/src/$oldname"; diff --git a/src/gl-mirror-push b/src/gl-mirror-push index 70514cb..e7054e2 100755 --- a/src/gl-mirror-push +++ b/src/gl-mirror-push @@ -25,6 +25,7 @@ hn=`get_rc_val GL_HOSTNAME` # get repo name then check if it's a local or slave (ie we're not the master) [ -z "$1" ] && die fatal: missing reponame argument repo=$1; shift +repo=${repo%.git} REPO_BASE=`get_rc_val REPO_BASE` cd $REPO_BASE/$repo.git 2>/dev/null || die fatal: could not change directory to "$repo" diff --git a/src/gl-mirror-shell b/src/gl-mirror-shell index d2b6489..80534dc 100755 --- a/src/gl-mirror-shell +++ b/src/gl-mirror-shell @@ -39,6 +39,11 @@ die "fatal: GL_HOSTNAME not set in rc; mirroring disabled\n" unless $GL_HOSTNAME # ---------------------------------------------------------------------------- +die "please read the gitolite mirroring documentation; this program is too +critical for you to just run it based on a 'usage' message.\n" if not @ARGV or $ARGV[0] eq '-h'; + +# ---------------------------------------------------------------------------- + # deal with local invocations first # on the "master", run from a shell, for one specific repo, with an optional @@ -47,6 +52,7 @@ die "fatal: GL_HOSTNAME not set in rc; mirroring disabled\n" unless $GL_HOSTNAME if ( ($ARGV[0] || '') eq 'request-push' and not $ENV{SSH_ORIGINAL_COMMAND} ) { shift; my $repo = shift or die "fatal: missing reponame\n"; + $repo =~ s/\.git$//; -d "$REPO_BASE/$repo.git" or die "fatal: no such repo?\n"; # this is the default argument if no slave list or key is supplied @@ -77,8 +83,6 @@ if ( ($ARGV[0] || '') eq 'request-push' and not $ENV{SSH_ORIGINAL_COMMAND} ) { exit 0; } -unless (@ARGV) { print STDERR "fatal: missing command\n"; exit 1; } - # ---------- # now the remote invocations; log it, then get the sender name @@ -107,6 +111,7 @@ if ($soc eq 'info') { if ($soc =~ /^git-receive-pack '(\S+)'$/) { my $repo = $1; + $repo =~ s/\.git$//; die "fatal: invalid characters in $repo\n" unless $repo =~ $REPONAME_PATT; my $mm = mirror_mode($repo); @@ -134,11 +139,12 @@ if ($soc =~ /^git-receive-pack '(\S+)'$/) { if ($soc =~ /^request-push (\S+)$/) { my $repo = $1; + $repo =~ s/\.git$//; die "fatal: invalid characters in $repo\n" unless $repo =~ $REPONAME_PATT; die "$ABRT fatal: $GL_HOSTNAME ==//==> $sender refused: not in slave list\n" unless mirror_listslaves($repo) =~ /(^|\s)$sender(\s|$)/; print STDERR "$GL_HOSTNAME ==== ($repo) ===> $sender\n"; # just one sender, and we've checked that he is "on the list". Foreground... - system("$ENV{GL_BINDIR}/gl-mirror-push", $repo, "-fg", $sender); + wrap_system("$ENV{GL_BINDIR}/gl-mirror-push", $repo, "-fg", $sender); exit; } @@ -156,6 +162,8 @@ if ($soc =~ /^USER=(\S+) SOC=(git-receive-pack '(\S+)')$/) { my $user = $1; $ENV{SSH_ORIGINAL_COMMAND} = $2; my $repo = $3; + $repo =~ s/\.git$//; + $repo =~ s(^/)(); die "fatal: invalid characters in $user\n" unless $user =~ $USERNAME_PATT; die "fatal: invalid characters in $repo\n" unless $repo =~ $REPONAME_PATT; die "$ABRT fatal: $GL_HOSTNAME <==//== $sender redirected push rejected\n" unless mirror_redirectOK($repo, $sender); diff --git a/src/gl-setup b/src/gl-setup index 7bf8881..1970d93 100755 --- a/src/gl-setup +++ b/src/gl-setup @@ -18,16 +18,42 @@ GL_PACKAGE_CONF=/tmp/share/gitolite/conf # pubkey file if you happen to have lost all gitolite-access to the repos (but # do have shell access via some other means) +# ---------------------------------------------------------------------- +# local functions +# ---------------------------------------------------------------------- + die() { echo "$@" >&2; exit 1; } get_rc_val() { `dirname $0`/gl-query-rc $1 } -TEMPDIR=`mktemp -d -t tmp.XXXXXXXXXX` +# ---------------------------------------------------------------------- +# tempdir setup +# ---------------------------------------------------------------------- + +TEMPDIR=`perl -MFile::Temp -l -e 'print File::Temp::tempdir("tmp.XXXXXXXXXX", TMPDIR => 1);'` export TEMPDIR trap "/bin/rm -rf $TEMPDIR" 0 +# ---------------------------------------------------------------------- +# argument handling +# ---------------------------------------------------------------------- + +# save arguments for use in commit message later +args="$*" + +if [ "$1" = "-h" ] +then + echo Usage: + echo " gl-setup [-q] [-q] [YourName.pub] # ssh mode" + echo " gl-setup [-q] [-q] [YourName] # http mode" + echo + echo "Please see 'appendix d' in doc/install.mkd for more. (Online at" + echo " http://sitaramc.github.com/gitolite/install.html#gl-setup)" + exit 1 +fi + # quiet mode; only used to suppress popping up an editor on a new rc file if [ "$1" = "-q" ] then @@ -35,6 +61,17 @@ then quiet=1 fi +# extra quiet mode (second '-q'); suppress the lint check at the end +if [ "$1" = "-q" ] +then + shift + nolint=1 +fi + +# ---------------------------------------------------------------------- +# get the admin_name and (usually) the pubkey file name +# ---------------------------------------------------------------------- + if [ -n "$GITOLITE_HTTP_HOME" ] then HOME=$GITOLITE_HTTP_HOME @@ -51,6 +88,10 @@ else fi fi +# ---------------------------------------------------------------------- +# report changes to rc file (for manual fixing) or setup a new rc file +# ---------------------------------------------------------------------- + export GL_RC GL_RC=`get_rc_val GL_RC 2>/dev/null` [ -z "$GL_RC" ] && GL_RC=$HOME/.gitolite.rc @@ -62,7 +103,7 @@ then } print_rc_vars $GL_PACKAGE_CONF/example.gitolite.rc > $TEMPDIR/.newvars print_rc_vars $GL_RC > $TEMPDIR/.oldvars - comm -23 $TEMPDIR/.newvars $TEMPDIR/.oldvars > $TEMPDIR/.diffvars + grep -f $TEMPDIR/.oldvars -v $TEMPDIR/.newvars > $TEMPDIR/.diffvars if [ -s $TEMPDIR/.diffvars ] then cp $GL_PACKAGE_CONF/example.gitolite.rc $HOME/.gitolite.rc.new @@ -88,6 +129,10 @@ else fi fi +# ---------------------------------------------------------------------- +# setup ~/.ssh +# ---------------------------------------------------------------------- + # setup ssh stuff. We break our normal rule that we will not fiddle with # authkeys etc., because in this case it seems appropriate ( @@ -98,6 +143,10 @@ fi chmod go-w . .ssh .ssh/authorized_keys ) +# ---------------------------------------------------------------------- +# setup gitolite's env vars +# ---------------------------------------------------------------------- + export GL_BINDIR export REPO_BASE export GL_ADMINDIR @@ -105,42 +154,50 @@ GL_BINDIR=` get_rc_val GL_BINDIR ` REPO_BASE=` get_rc_val REPO_BASE ` GL_ADMINDIR=`get_rc_val GL_ADMINDIR` -# now we get to gitolite itself +# ---------------------------------------------------------------------- +# setup hooks, admindir, the admin repo +# ---------------------------------------------------------------------- gl-install -q [ -f $GL_ADMINDIR/conf/gitolite.conf ] || { - cat <<EOF | cut -c9- > $GL_ADMINDIR/conf/gitolite.conf + echo " repo gitolite-admin RW+ = $admin_name repo testing RW+ = @all -EOF + " | cut -c9- > $GL_ADMINDIR/conf/gitolite.conf } [ -n "$pubkey_file" ] && cp $pubkey_file $GL_ADMINDIR/keydir touch $HOME/.ssh/authorized_keys gl-compile-conf -q -# setup push-to-admin -[ -n "$pubkey_file" ] && ( +# setup the admin repo +[ -n "$pubkey_file" ] || [ -n "$GITOLITE_HTTP_HOME" ] && ( cd $HOME; cd $REPO_BASE/gitolite-admin.git GIT_WORK_TREE=$GL_ADMINDIR; export GIT_WORK_TREE git add conf/gitolite.conf keydir git config --get user.email >/dev/null || git config user.email $USER@`hostname` git config --get user.name >/dev/null || git config user.name "$USER on `hostname`" - git diff --cached --quiet 2>/dev/null || git commit -am start + git diff --cached --quiet 2>/dev/null || git commit -am "gl-setup $args" ) # now that the admin repo is created, you have to set the hooks properly; best # do it by running install again gl-install -q -# ---- +# ---------------------------------------------------------------------- +# lint check on ssh keys +# ---------------------------------------------------------------------- + +[ -z "$nolint" ] && { + # the never-ending quest to help with bloody ssh issues... + cd $GL_ADMINDIR/keydir + [ -n "$pubkey_file" ] && $GL_BINDIR/sshkeys-lint -q -a $admin_name < $HOME/.ssh/authorized_keys +} -# the never-ending quest to help with bloody ssh issues... -cd $GL_ADMINDIR/keydir -[ -n "$pubkey_file" ] && $GL_BINDIR/sshkeys-lint -q -a $admin_name < $HOME/.ssh/authorized_keys +# ---------------------------------------------------------------------- exit 0 diff --git a/src/gl-system-install b/src/gl-system-install index d7df7e4..b8b6377 100755 --- a/src/gl-system-install +++ b/src/gl-system-install @@ -1,117 +1,144 @@ -#!/bin/sh +#!/usr/bin/perl +use strict; +use warnings; +use English; # so I can say $EUID instead of $> +use File::Path qw(mkpath); -# install the gitolite software *system wide*. Not too robust, fancy, etc., -# but does have a usage message and catches simple problems. +# install the gitolite software *system wide*. -usage() { echo " - Usage: - $0 [shared-bin-dir shared-conf-dir shared-hooks-dir] +# This program does for a manual install (root or non-root method) what +# doc/packaging.mkd describes is needed to be done by a packager. - Installs the gitolite software (just the software, not keys or repos) - within \$HOME when invoked by a user, or system-wide when invoked by root. +# Packagers can also use this program to do the same thing if they wish. - Takes 0 or 3 absolute paths. The first one must be part of \$PATH. +my ( $bin_dir, $conf_dir, $hooks_dir ); - Examples: - # as root - $0 +check_args(); +argv_or_defaults(); +check_dirs(); - # this defaults to: - $0 /usr/local/bin /var/gitolite/conf /var/gitolite/hooks +use FindBin; +# we assume the standard gitolite source tree is here! +chdir( $FindBin::Bin . "/.." ) or die "can't cd: $!\n"; - # as a normal user - $0 +# notice the 'and' for failure after system() calls, because they return +# "shell truth" not "perl truth" - # this defaults to: - $0 \$HOME/bin \$HOME/share/gitolite/conf \$HOME/share/gitolite/hooks +# copy src +system("cp src/* $bin_dir") and die "cp src/* to $bin_dir failed"; - [RPM packagers: you can supply a 4th argument to specify a 'buildroot' - directory. DEB folks would call this a 'DESTDIR', I believe. In this - usage the first 3 arguments are NOT optional] -" - exit 1; -} +# fixup GL_PACKAGE_CONF in gl-setup +replace( "/tmp/share/gitolite/conf", $conf_dir, "$bin_dir/gl-setup" ); -die() { echo >&2; echo "$@" >&2; echo >&2; echo Run "$0 -h" for a detailed usage message. >&2; exit 1; } - -[ "$1" = "-h" ] && usage +# record which version is being sent across; we assume it's HEAD +record_version(); -validate_dir() { - echo $1 | grep '^/' >/dev/null || die "$1 should be an absolute path" - [ -d $1 ] || mkdir -p $1 || die "$1 does not exist and could not be created" -} +# copy conf +system("cp -R conf/* $conf_dir") and die "cp conf/* to $conf_dir failed"; -# if we have a buildroot, set that up first -buildroot=$4; -[ -n "$buildroot" ] && validate_dir $buildroot -[ -n "$buildroot" ] && buildroot=$buildroot/ - -# either all 3 args must be supplied or none at all -[ -n "$1" ] && [ -z "$3" ] && die "I need all 3 directories or none at all" -# supply default values to args 1, 2, and 3 if not provided -[ -z "$1" ] && { - euid=`perl -e 'print $>'` - if [ "$euid" = "0" ] - then - set /usr/local/bin /var/gitolite/conf /var/gitolite/hooks - else - set $HOME/bin $HOME/share/gitolite/conf $HOME/share/gitolite/hooks - fi - echo "using default values for EUID=$euid:" >&2 - echo "$@" >&2 -} +# fixup GL_PACKAGE_CONF and GL_PACKAGE_HOOKS in the example rc +replace( "/tmp/share/gitolite/conf", $conf_dir, "$conf_dir/example.gitolite.rc" ); +replace( "/tmp/share/gitolite/hooks", $hooks_dir, "$conf_dir/example.gitolite.rc" ); -gl_bin_dir=$1; validate_dir $buildroot$gl_bin_dir -gl_conf_dir=$2; validate_dir $buildroot$gl_conf_dir -gl_hooks_dir=$3; validate_dir $buildroot$gl_hooks_dir +# copy hooks +system("cp -R hooks/* $hooks_dir") and die "cp hooks/* to $hooks_dir failed"; -bindir=`echo $0 | perl -lpe 's/^/$ENV{PWD}\// unless /^\//; s/\/[^\/]+$//;'` -cd $bindir/.. # we assume the standard gitolite source tree is here! +# this is some extra gunk for people with crap setups +path_advice(); -cp src/* $buildroot$gl_bin_dir || die "cp src/* to $buildroot$gl_bin_dir failed" -perl -lpi -e "s(^GL_PACKAGE_CONF=.*)(GL_PACKAGE_CONF=$gl_conf_dir)" $buildroot$gl_bin_dir/gl-setup +exit 0; -# record which version is being sent across; we assume it's HEAD -if git rev-parse --is-inside-work-tree >/dev/null 2>&1 -then - git describe --tags --long --dirty=-dt 2>/dev/null > conf/VERSION || die "git describe failed -- your git is probably too old" -else - [ -f conf/VERSION ] || echo '(unknown)' > conf/VERSION -fi +# ---------------------------------------------------------------------- -cp -R conf/* $buildroot$gl_conf_dir || die "cp conf/* to $buildroot$gl_conf_dir failed" -perl -lpi \ - -e "s(^#\s*\\\$GL_PACKAGE_CONF\s*=.*)(\\\$GL_PACKAGE_CONF = '$gl_conf_dir';)" \ - $buildroot$gl_conf_dir/example.gitolite.rc -perl -lpi \ - -e "s(^#\s*\\\$GL_PACKAGE_HOOKS\s*=.*)(\\\$GL_PACKAGE_HOOKS = '$gl_hooks_dir';)" \ - $buildroot$gl_conf_dir/example.gitolite.rc +sub check_args { + return unless @ARGV; + return if @ARGV == 3; + usage(); +} -cp -R hooks/* $buildroot$gl_hooks_dir || die "cp hooks/* to $buildroot$gl_hooks_dir failed" +sub argv_or_defaults { + ( $bin_dir, $conf_dir, $hooks_dir ) = @ARGV; + return if @ARGV; + + unless (@ARGV) { + my $HOME = $ENV{HOME}; + if ( $EUID eq "0" ) { + ( $bin_dir, $conf_dir, $hooks_dir ) = qw(/usr/local/bin /var/gitolite/conf /var/gitolite/hooks); + } else { + ( $bin_dir, $conf_dir, $hooks_dir ) = ( "$HOME/bin", "$HOME/share/gitolite/conf", "$HOME/share/gitolite/hooks" ); + } + print STDERR "using default values for EUID=$EUID:\n"; + print STDERR join( ", ", $bin_dir, $conf_dir, $hooks_dir ), "\n"; + } +} -# ---- +sub check_dirs { + for my $dir ( $bin_dir, $conf_dir, $hooks_dir ) { + die "$dir should be an absolute path\n" unless $dir =~ m(^/); + mkpath($dir); + -d $dir or die "$dir does not exist and could not be created\n"; + } +} -# check if $gl_bin_dir is in $PATH and advise the user if needed -which=`which gl-setup 2>/dev/null` +sub replace { + my ( $old, $new, $file ) = @_; + system("perl -lpi -e 's($old)($new)' $file"); +} -path_advice=" -Since gl-setup MUST be run from the PATH (and not as src/gl-setup or such), -you must fix this before running gl-setup. The simplest way is to add +sub record_version { + # this is really much easier in plain shell :( + if ( system("git rev-parse --is-inside-work-tree >/dev/null 2>&1") ) { + # for system() calls, perl 'true/success' is shell 'false/fail', which + # means the command failed; we are not in a git work tree + -f "conf/VERSION" or system("echo '(unknown)' > conf/VERSION"); + } else { + system("git describe --tags --long --dirty=-dt 2>/dev/null > conf/VERSION") + and die "git describe failed -- your git is probably too old"; + } +} - PATH=$gl_bin_dir:\$PATH +sub path_advice { + my $path_advice = " + Since gl-setup MUST be run from the PATH (and not as src/gl-setup or + such), you must fix this before running gl-setup. Just add + + PATH=$bin_dir:\$PATH + + to the end of your bashrc or similar file. You can even simply do that + manually each time you log in and want to run a gitolite command.\n"; + + for my $p ( split( ':', $ENV{PATH} ) ) { + return if $p eq $bin_dir; # all is well + + if ( -x "$p/gl-setup" ) { + #<<< + die " ***** WARNING *****\n" . + " you have installed the sources into $bin_dir, but\n" . + " $p in your \$PATH *also* contains gl-setup.\n" . + " This is almost certainly going to confuse you or me later.\n" . + $path_advice; + #>>> + } + } + + #<<< + die " ***** WARNING *****\n" . + " gl-setup is not in your \$PATH.\n" . + $path_advice; + #>>> +} -to the end of your bashrc or similar file. You can even simply run that -command manually each time you log in and want to run a gitolite command." +sub usage { + print " +Usage: + gl-system-install [bin-dir conf-dir hooks-dir] -[ -z "$which" ] && die " ***** WARNING ***** -gl-setup is not in your \$PATH. -$path_advice" +Requires all 3 arguments or none. All arguments supplied must be absolute +paths. The following defaults are used if arguments are not supplied: -which=`dirname $which` -[ "$which" = "$gl_bin_dir" ] || die " ***** WARNING ***** -$which precedes $gl_bin_dir in your \$PATH, -and it *also* contains gl-setup. This is almost certainly going to confuse -you or me later. -$path_advice" + as normal user: \$HOME/bin, \$HOME/share/gitolite/conf, \$HOME/share/gitolite/hooks + as root: /usr/local/bin, /var/gitolite/conf, /var/gitolite/hooks +"; + exit 1; +} -exit 0 diff --git a/src/gl-tool b/src/gl-tool index 256a47a..d95a3bc 100755 --- a/src/gl-tool +++ b/src/gl-tool @@ -13,7 +13,7 @@ use gitolite_rc; use gitolite; sub usage { print <DATA>; exit 1; } -usage() unless (@ARGV); +usage() if (not @ARGV) or $ARGV[0] eq '-h'; my $cmd = shift; my $pub = shift; diff --git a/src/sshkeys-lint b/src/sshkeys-lint index 96c027f..a18a306 100755 --- a/src/sshkeys-lint +++ b/src/sshkeys-lint @@ -8,7 +8,8 @@ use warnings; use Getopt::Long; my $admin = 0; my $quiet = 0; -GetOptions('admin|a=s' => \$admin, 'quiet|q' => \$quiet); +my $help = 0; +GetOptions('admin|a=s' => \$admin, 'quiet|q' => \$quiet, 'help|h' => $help); use Data::Dumper; $Data::Dumper::Deepcopy = 1; @@ -31,7 +32,7 @@ sub msg { print "sshkeys-lint: " . ( $warning ? "WARNING: " : "" ) . $_ for @_; } -@ARGV or not -t or usage(); +usage() if not @ARGV and -t or $help; our @pubkeyfiles = @ARGV; @ARGV = (); # ------------------------------------------------------------------------ |