Saher El-Neklawy A blog

SVN post-commit hook cronjob

Few SVN hosting sites provide ssh access to their svn servers. Such is needed to create hooks, like a post-commit hook that sends an email with every commit. Such hooks are often required by the development team. This article discusses the creation of a cron job that polls the SVN repository to simulate a post-commit hook that sends an email with every commit.

Setting up sendEmail

sendEmail is a nice tool to send emails via command line. This is needed to script in the cronjob sending an email. On ubuntu, install it from apt-get by:

sudo apt-get install sendemail libio-socket-ssl-perl libcrypt-ssleay-perl

The latter 2 packages are needed for connecting to an SMTP server that uses a secure connection (like Gmail, which is used in the example).

The post-commit hook script

The following is a python script, that could be added as an entry in the cron table
[sourcecode language="python"]
#! /usr/bin/env python

import os,re

log_file = LOG_DIR
svn_log_seperator = '------------------------------------------------------------------------'
svn_dir = SVN_DIR
mail_filter = '[special mail identifier in subject]'
message_file = '/tmp/commit_mail'

mail_from = MAIL_FROM
mail_to = MAIL_TO

smtp_server = "smtp.gmail.com:587"
smtp_user = SMTP_USER
smtp_pass = SMTP_PASS

def send_mail(subject,mail):
mail_file = open(message_file,'w')
mail_file.write(mail)
mail_file.close()
mail_command = 'sendEmail -f %s -t %s -u "%s" -s %s -xu "%s" -xp "%s" -o message-file="%s"' % (mail_from, mail_to, subject, smtp_server, smtp_user, smtp_pass,message_file)
print mail_command
os.system(mail_command)

print "analyzing old log file"

old_log_f = open(log_file)
old_log = old_log_f.read().split(svn_log_seperator)
old_log_f.close()

print "updating svn"
os.system("/usr/local/bin/svn update %s" % svn_dir)
os.system("/usr/local/bin/svn log %s > %s" % (svn_dir,log_file))
print "got new log"

new_log_f = open(log_file)
new_log = new_log_f.read().split(svn_log_seperator)
new_log_f.close()

delta = set(new_log) - set(old_log)

for commit in delta:
l = [x for x in commit.split('\n') if x]
details = l[0].split('|')
subject = "%s %s %s" %(mail_filter,details[0],details[1])
f_diff=os.popen('/usr/local/bin/svn diff -c %s %s' % (details[0], svn_dir))
diff = f_diff.read()
f_diff.close()
mail = "%s\n%s" % (commit, diff)
send_mail(subject,mail)
[/sourcecode]

Perquisites before running the script

      Having a working copy of the svn reposity
      Running the following command once before the script:

      svn log > $PATH_TO_LOG_FILE