From 8bffbfa02acfbd9674d5dfd8c57864b20597f93d Mon Sep 17 00:00:00 2001 From: Sitaram Chamarty Date: Sat, 24 Mar 2012 09:12:10 +0530 Subject: [PATCH] 3 old VREFs moved in, untested but they're just update hooks anyway so they should work fine --- src/VREF/DUPKEYS | 45 ++++++++++++++++++++++++++++++ src/VREF/EMAIL-CHECK | 66 ++++++++++++++++++++++++++++++++++++++++++++ src/VREF/MERGE-CHECK | 49 ++++++++++++++++++++++++++++++++ 3 files changed, 160 insertions(+) create mode 100755 src/VREF/DUPKEYS create mode 100755 src/VREF/EMAIL-CHECK create mode 100644 src/VREF/MERGE-CHECK diff --git a/src/VREF/DUPKEYS b/src/VREF/DUPKEYS new file mode 100755 index 0000000..7e479fa --- /dev/null +++ b/src/VREF/DUPKEYS @@ -0,0 +1,45 @@ +#!/bin/bash + +# gitolite VREF to detect duplicate public keys + +# see gitolite doc/vref.mkd for what the arguments are +sha=$3 + +# git sets this; and we don't want it at this point... +unset GIT_DIR + +# paranoia +set -e + +# setup the temp area +export TMPDIR=$GL_REPO_BASE_ABS +export tmp=$(mktemp -d -t gl-internal-temp-repo.XXXXXXXXXX); +trap "rm -rf $tmp" EXIT; + +git archive $sha keydir | tar -C $tmp -xf - + # DO NOT try, say, 'GIT_WORK_TREE=$tmp git checkout $sha'. It'll screw up + # both the 'index' and 'HEAD' of the repo.git. Screwing up the index is + # BAD because now it goes out of sync with $GL_ADMINDIR. Think of a push + # that had a deleted pubkey but failed a hooklet for some reason. A + # subsequent push that fixes the error will now result in a $GL_ADMINDIR + # that still *has* that deleted pubkey!! + + # And this is equally applicable to cases where you're using a + # post-receive or similar hook to live update a web site or something, + # which is a pretty common usage, I am given to understand. + +cd $tmp + +for f in `find keydir -name "*.pub"` +do + ssh-keygen -l -f "$f" +done | perl -ane ' + die "FATAL: $F[2] is a duplicate of $seen{$F[1]}\n" if $seen{$F[1]}; + $seen{$F[1]} = $F[2]; +' + +# as you can see, a vref can also 'die' if it wishes to, and it'll take the +# whole update with it if it does. No messing around with sending back a +# vref, having it run through the matches, and printing the DENIED message, +# etc. However, if your push is running from a script, and that script is +# looking for the word "DENIED" or something, then this won't work... diff --git a/src/VREF/EMAIL-CHECK b/src/VREF/EMAIL-CHECK new file mode 100755 index 0000000..34c66f5 --- /dev/null +++ b/src/VREF/EMAIL-CHECK @@ -0,0 +1,66 @@ +#!/usr/bin/perl + +# gitolite VREF to check if all *new* commits have author == pusher + +# THIS IS NOT READY TO USE AS IS +# ------------------------------ +# you MUST change the 'email_ok()' sub to suit *YOUR* site's +# gitolite username -> author email mapping! + +# See bottom of the program for important philosophical notes. + +use strict; +use warnings; + +# mapping between gitolite userid and correct email address is encapsulated in +# this subroutine; change as you like +sub email_ok { + my ($author_email) = shift; + my $expected_email = "$ENV{GL_USER}\@atc.tcs.com"; + return $author_email eq $expected_email; +} + +my ( $ref, $old, $new ) = @ARGV; +for my $rev (`git log --format="%ae\t%h\t%s" $new --not --all`) { + chomp($rev); + my ( $author_email, $hash, $subject ) = split /\t/, $rev; + + # again, we use the trick that a vref can just choose to die instead of + # passing back a vref, having it checked, etc., if it's more convenient + die "$ENV{GL_USER}, you can't push $hash authored by $author_email\n" . "\t(subject of commit was $subject)\n" + unless email_ok($author_email); +} + +exit 0; + +__END__ + +The following discussion is for people who want to enforce this check on ALL +their developers (i.e., not just the newbies). + +Doing this breaks the "D" in "DVCS", forcing all your developers to work to a +centralised model as far as pushes are concerned. It prevents amending +someone else's commit and pushing (this includes rebasing, cherry-picking, and +so on, which are all impossible now). It also makes *any* off-line +collabaration between two developers useless, because neither of them can push +the result to the server. + +PHBs should note that validating the committer ID is NOT the same as reviewing +the code and running QA/tests on it. If you're not reviewing/QA-ing the code, +it's probably worthless anyway. Conversely, if you *are* going to review the +code and run QA/tests anyway, then you don't really need to validate the +author email! + +In a DVCS, if you *pushed* a series of commits, you have -- in some sense -- +signed off on them. The most formal way to "sign" a series is to tack on and +push a gpg-signed tag, although most people don't go that far. Gitolite's log +files are designed to preserve that accountability to *some* extent, though; +see contrib/adc/who-pushed for an admin defined command that quickly and +easily tells you who *pushed* a particular commit. + +Anyway, the point is that the only purpose of this script is to + + * pander to someone who still has not grokked *D*VCS + OR + * tick off an item in some stupid PHB's checklist + diff --git a/src/VREF/MERGE-CHECK b/src/VREF/MERGE-CHECK new file mode 100644 index 0000000..07f0351 --- /dev/null +++ b/src/VREF/MERGE-CHECK @@ -0,0 +1,49 @@ +#!/usr/bin/perl +use strict; +use warnings; + +# gitolite VREF to check if there are any merge commits in the current push. + +# THIS IS DEMO CODE; please read all comments below as well as +# doc/vref.mkd before trying to use this. + +# usage in conf/gitolite.conf goes like this: + +# - VREF/MERGE_CHECK/master = @all +# # reject only if the merge commit is being pushed to the master branch +# - VREF/MERGE_CHECK = @all +# # reject merge commits to any branch + +my $ref = $ARGV[0]; +my $oldsha = $ARGV[1]; +my $newsha = $ARGV[2]; +my $refex = $ARGV[6]; + +# The following code duplicates some code from parse_conf_line() and some from +# check_ref(). This duplication is the only thing that is preventing me from +# removing the "M" permission code from 'core' gitolite and using this +# instead. However, it does demonstrate how you would do this if you had to +# create any other similar features, for example someone wanted "no non-merge +# first-parent", which is far too specific for me to add to 'core'. + +# -- begin duplication -- +my $branch_refex = $ARGV[7] || ''; +if ($branch_refex) { + $branch_refex =~ m(^refs/) or $branch_refex =~ s(^)(refs/heads/); +} else { + $branch_refex = 'refs/.*'; +} +exit 0 unless $ref =~ /^$branch_refex/; +# -- end duplication -- + +# we can't run this check for tag creation or new branch creation, because +# 'git log' does not deal well with $oldsha = '0' x 40. +if ( $oldsha eq "0" x 40 or $newsha eq "0" x 40 ) { + print STDERR "ref create/delete ignored for purposes of merge-check\n"; + exit 0; +} + +my $ret = `git rev-list -n 1 --merges $oldsha..$newsha`; +print "$refex FATAL: merge commits not allowed\n" if $ret =~ /./; + +exit 0;