Permalink
Browse files

Mass commit of stock ADCs

  • Loading branch information...
1 parent 17b48da commit 2bea1b9565b5a2aa0c0aec5f0e6bad1e02e29394 Adrien Thebo committed Mar 15, 2012
View
@@ -0,0 +1,52 @@
+# F=shipped_ADCs brief descriptions of the shipped ADCs (admin-defined commands)
+
+(...with pointers to further information where needed)
+
+----
+
+**able**: enable/disable push access temporarily (such as for taking backups
+or other admin chores); details [here][able]. This ADC is meant only for
+admins.
+
+**delete-branch**: allow someone to delete a branch that they themselves
+created. (i.e., when the user had RWC, but not RWCD, permissions). Details on
+this ADC are [here][dbsha]; details on RWC/RWD/RWCD etc are [here][rwcd].
+
+[dbsha]: https://github.com/sitaramc/gitolite/commit/89b68bf5ca99508caaa768c60ce910d7e0a29ccf
+
+**fork**: Think of it as a server-side clone; details [here][fork].
+
+**get-rights-and-owner.in-perl**: Most of the ADCs are in shell, so this is a
+sample of how to write an ADC in perl.
+
+**git-annex-shell**: allows git-annex to store and retrieve annexed file content in
+repositories. To use, install in `$GL_ADC_PATH/ua/git-annex-shell`
+
+**gl-reflog**: show a fake "reflog" from the server, and allow recovery from
+deleted branches and bad force pushes; details in source.
+
+**help**: not all shipped ADCs may be enabled by the site admin. Conversely
+the admin may create and install his own ADCs that dont ship with gitolite
+itself. This ADC displays site-local help, if the site admin enabled it.
+
+**hub**: allow "pull requests" a la github; details [here][hub].
+
+**rm**, **lock**, and **unlock**:<br>
+**trash**, **list-trash**, and **restore**:
+
+> two families of repo deletion commands; details [here][wild_repodel]
+
+**sudo**: allow admin to run ADCs on behalf of a user. Useful in support
+situations I guess. Details in source.
+
+Note: the Unix "sudo" and "su" programs are most often used to acquire
+*higher* privileges, although they're actually designed to go the other way
+also. In gitolite we do not do the former, only the latter (i.e., a normal
+gitolite user cannot do admin-stuff using this ADC).
+
+**su-expand**, **su-getperms**, **su-setperms**: as above, but for the
+internal commands 'expand', 'getperms', and 'setperms'. (These commands are
+not ADCs so you cannot simply use the 'sudo' ADC described above).
+
+**who-pushed**: find the last person to push a given commit; details in
+source.
View
@@ -0,0 +1,56 @@
+#!/bin/sh
+
+. $(dirname $0)/adc.common-functions
+
+is_admin || die "just *what* are you trying to pull, young man?"
+
+op=$1
+shift
+
+locs=
+while [ -n "$1" ]
+do
+ case $1 in
+ '@all' )
+ locs="$locs $HOME"
+ ;;
+ * )
+ loc="$GL_REPO_BASE_ABS/$1.git"
+ [ -d $loc ] && locs="$locs $GL_REPO_BASE_ABS/$1.git"
+ [ -d $loc ] || echo "ignoring $1..."
+ ;;
+ esac
+ shift
+done
+
+[ -z "$locs" ] && die "give me '@all' or some reponame"
+
+case $op in
+ en|enable )
+ for l in $locs
+ do
+ rm -fv $l/.gitolite.down
+ done
+ ;;
+ dis|disable )
+
+ TEMPDIR=$(mktemp -d -t tmp.XXXXXXXXXX)
+ export TEMPDIR
+ trap "/bin/rm -rf $TEMPDIR" 0
+
+ echo 'type the message to be shown to users when they try to push; end with Ctrl-D:'
+ echo > $TEMPDIR/msg
+ cat >> $TEMPDIR/msg
+ echo disabling following locations with message:
+ cat $TEMPDIR/msg
+ echo
+ for l in $locs
+ do
+ cat $TEMPDIR/msg > $l/.gitolite.down
+ echo $l
+ done
+ ;;
+ * )
+ die "argument 1 must be 'en' or 'dis'"
+ ;;
+esac
@@ -0,0 +1,132 @@
+#!/bin/sh
+
+# please make sure this file is NOT chmod +x
+
+# this file contains settings for all ADCs at the top, then functions that you
+# can call from shell scripts. Other files in this directory have examples.
+
+# all uses require you to "source" this file, like so:
+
+# # at the top of your ADC
+# . $(dirname $0)/adc.common-functions
+
+# then you use one of the following functions, like so:
+
+# can_create reponame || die "you can't create reponame"
+# can_write reponame || die "you can't write reponame"
+# can_read reponame || die "you can't read reponame"
+# is_admin || die "you're not an admin"
+
+# IMPORTANT NOTE: all the can_* functions set $repo to the normalised reponame
+# (i.e., with '.git' extension removed if it was supplied).
+
+# ------------------------------------------------------------------------------
+
+# settings for various ADCs, collected in one place for ease of keeping local
+# settings intact during upgrades (you only have to worry about this file
+# now). Documentation for the variables, however, is in the respective ADC
+
+# settings for 'rm' ADC
+ARE_YOU_SURE=1
+USE_LOCK_UNLOCK=1
+
+# settings for 'trash' ADC
+TRASH_CAN=$GL_REPO_BASE_ABS/deleted
+TRASH_SUFFIX=`date +%Y-%m-%d_%H:%M:%S`
+
+# settings for 'hub' ADC
+BASE_FETCH_URL="git://gl.example.com"
+GL_FORKED_FROM="gl-forked-from"
+ # KDE may set this to kde-cloned-from for historical reasons
+
+# Change to 1 to make -list the default action for the 'help' command
+HELP_LIST_DEFAULT=0
+
+# name of "admin" group (see is_admin() below before uncommenting)
+# ADMIN_GROUPNAME=admins
+
+# ------------------------------------------------------------------------------
+
+die() { echo "$@"; exit 1; }
+
+# test an option value more concisely
+opt() {
+ [ "$1" = "1" ] && return 0
+ return 1
+}
+
+valid_owned_repo() {
+ # check that an arg passed is a valid repo and the current user owns it
+ [ -z "$1" ] && die need a repo name
+ get_rights_and_owner $1
+ [ "$owner" = "$GL_USER" ] || die "$repo does not exist or is not yours!"
+
+ # and we sneak this in too, quietly :)
+ cd $GL_REPO_BASE_ABS
+}
+
+# NOTE: this also sets $repo to the normalised (without .git suffix) reponame
+get_rights_and_owner() {
+ local ans
+ repo=${1%.git}
+ ans=$(perl -I$GL_BINDIR -Mgitolite -e "cli_repo_rights('"$repo"')")
+
+ # set shell variables as needed
+ owner=${ans#* }
+ rights=${ans% *}
+ echo $rights | grep C >/dev/null 2>&1 && perm_create=yes || perm_create=
+ echo $rights | grep R >/dev/null 2>&1 && perm_read=yes || perm_read=
+ echo $rights | grep W >/dev/null 2>&1 && perm_write=yes || perm_write=
+}
+
+can_create() {
+ get_rights_and_owner ${1%.git}
+ [ -z "$perm_create" ] && return 1
+ return 0
+}
+
+can_write() {
+ get_rights_and_owner ${1%.git}
+ [ -z "$perm_write" ] && return 1
+ return 0
+}
+
+can_read() {
+ get_rights_and_owner ${1%.git}
+ [ -z "$perm_read" ] && return 1
+ return 0
+}
+
+# ------------------------------------------------------------------------------
+
+# check if current user is an admin
+is_admin() {
+ # there are two ways to check if someone is an admin. The default (if
+ # ADMIN_GROUPNAME is not defined) is to check if they have write access to
+ # the admin repo
+
+ if [ -z "$ADMIN_GROUPNAME" ]
+ then
+ can_write gitolite-admin || return 1
+ return 0
+ fi
+
+ # the alternative way is to check membership in $ADMIN_GROUPNAME; please
+ # remember this method requires GL_BIG_CONFIG to be set
+
+ # TODO, pending the code to allow an external query of a user's "group"
+ # affiliations
+ in_group $ADMIN_GROUPNAME
+}
+
+# ------------------------------------------------------------------------------
+
+grouplist() {
+ perl -I$GL_BINDIR -Mgitolite -e "cli_grouplist()"
+}
+
+in_group() {
+ local g=$1
+ grouplist | egrep "(^| )$g( |$)" >/dev/null && return 0
+ return 1
+}
View
@@ -0,0 +1,84 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+
+# allow a user to delete a ref if the last create of the ref was done by the
+# same user, *and* it was done within a certain time limie
+
+# change this to suit your needs
+my $oldest = 60*60*24*7; # in seconds
+
+# use a generic error message to avoid information leak
+my $error = "didn't find repo/ref, or the ref is too old, or you did not create it\n";
+
+# ----
+
+die "ENV GL_RC not set\n" unless $ENV{GL_RC};
+die "ENV GL_BINDIR not set\n" unless $ENV{GL_BINDIR};
+
+unshift @INC, $ENV{GL_BINDIR};
+require gitolite or die "parse gitolite.pm failed\n";
+gitolite->import;
+
+# arg check
+die "need two arguments, a reponame and a refname\n" unless @ARGV == 2;
+# get the repo name
+my $repo = shift;
+$repo =~ s/\.git$//;
+# get the ref name to be deleted, and allow the same convenience shortcut
+# (prefix "refs/heads/" if it doesn't start with "refs/") as in the main
+# config file
+my $ref = shift;
+$ref =~ m(^refs/) or $ref =~ s(^)(refs/heads/);
+
+# XXX WARNING: we do not do any access control checking -- we just go by the
+# fact that if *you* created a branch within the last $limit seconds (default
+# value is 1 week), you are allowed to delete the branch.
+
+# find the earliest log entry we're willing to look at
+my $limit = `date -d '$oldest seconds ago' '+%F.%T'`;
+ # NOTE: this is the format that gitolite uses in its log entries (see sub
+ # 'get_logfilename in one of the pm files). The logic also depends on the
+ # fact that this is sortable, because we read backwards and stop when we
+ # reach something older than $limit
+chomp($limit);
+
+# find the last 2 log files; here also we depend on the fact that the file
+# *names* are time ordered when sorted
+my ($lf1, $lf2) = reverse sort glob("$ENV{GL_ADMINDIR}/logs/gitolite*log");
+
+my $found = 0;
+my($ts, $user, $ip, $cmd, $op, $oldsha, $newsha, $logrepo, $logref, $refrule);
+for my $lf ($lf1, $lf2) {
+ next unless $lf;
+ open(LF, "-|", "tac", $lf) or die "tac $lf failed: $!\n";
+ while (<LF>) {
+ ($ts, $user, $ip, $cmd, $op, $oldsha, $newsha, $logrepo, $logref, $refrule) = split /\t/;
+ next unless $refrule;
+ if ($ts le $limit) {
+ # we don't look at entries earlier than this
+ $found = -1;
+ last;
+ }
+ if ($op eq 'C' and $oldsha =~ /^0+$/ and $logrepo eq $repo and $logref eq $ref) {
+ # creation record found; no need to look at any more entries
+ $found = 1;
+ last;
+ }
+ }
+ last if $found;
+}
+# check user in creation record to make sure it is the same one
+if ($found == 1 and $user eq $ENV{GL_USER}) {
+ chdir("$ENV{GL_REPO_BASE_ABS}/$repo.git") or die "chdir $ENV{GL_REPO_BASE_ABS}/$repo.git failed: $!\n";
+ system("git", "update-ref", "-d", $ref, $newsha) and die "ref deletion failed\n";
+ warn "deleted $ref from $repo (created on $ts)\n";
+ # NOTE: we use warn so this gets into the log in some way; perhaps
+ # later we can adjust the format to more closely resemble a normal
+ # remote delete operation
+ exit 0;
+}
+
+print STDERR $error;
+exit 1;
View
@@ -0,0 +1,45 @@
+#!/bin/sh
+
+. $(dirname $0)/adc.common-functions
+
+[ -z "$GL_RC" ] && die "ENV GL_RC not set"
+[ -z "$2" ] && die "Usage: fork source_repo target_repo"
+
+# all the can_* functions set $repo
+can_read $1 || die "no read permissions on $repo"
+from=$repo
+
+can_create $2 || die "no create permissions on $repo"
+to=$repo
+
+# clone $from to $to
+git clone --bare -l $GL_REPO_BASE_ABS/$from.git $GL_REPO_BASE_ABS/$to.git
+[ $? -ne 0 ] && exit 1
+
+echo "$from forked to $to"
+
+# fix up creator, gitweb owner, and hooks
+cd $GL_REPO_BASE_ABS/$to.git
+echo $GL_USER > gl-creater
+git config gitweb.owner "$GL_USER"
+( $GL_BINDIR/gl-query-rc GL_WILDREPOS_DEFPERMS ) |
+ SSH_ORIGINAL_COMMAND="setperms $to" $GL_BINDIR/gl-auth-command $GL_USER
+
+# symlink hooks
+shopt -s nullglob
+# the order is important; "package" hooks must override same-named "user" hooks
+for i in `$GL_BINDIR/gl-query-rc GL_ADMINDIR`/hooks/common/* \
+ `$GL_BINDIR/gl-query-rc GL_PACKAGE_HOOKS `/common/*
+do
+ ln -sf $i $GL_REPO_BASE_ABS/$to.git/hooks
+done
+
+if [ -n "$GL_WILDREPOS_DEFPERMS" ]; then
+ echo "$GL_WILDREPOS_DEFPERMS" > gl-perms
+fi
+
+echo "$from" > gl-forked-from
+
+# run gitolite's post-init hook if you can (hook code expects GL_REPO to be set)
+export GL_REPO; GL_REPO="$to"
+[ -x hooks/gl-post-init ] && hooks/gl-post-init
Oops, something went wrong.

0 comments on commit 2bea1b9

Please sign in to comment.