Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
Client side svn commit hook
#!/usr/bin/env groovy
import groovy.text.SimpleTemplateEngine
import java.text.SimpleDateFormat
def chill = 5 //min
def projects = [
// 'projectName1':/C:\Project\project1/
// 'projectName2':/C:\Project\project2/
def subject="[<%=rev%>] [SVN:<%=name%>] [Author:<%=author%>]"
def body = """<%=name%> revision <%=rev%> report
Author: <%=author%>
Date: <%=date%>
Log Message:
//new! Rss feed template
def rssItem = """
<guid isPermaLink="false"><%=guid%></guid>
def engine = new SimpleTemplateEngine()
def BODY = engine.createTemplate(body)
def SUBJECT = engine.createTemplate(subject)
def RSS_ITEM = engine.createTemplate(rssItem)
def ps = new PrintStream(
new BufferedOutputStream(new FileOutputStream('svndiff.log')))
def printLog(def msg, def ps){
def df = new SimpleDateFormat()
println "[${df.format(new Date())}] $msg"
ps.println "[${df.format(new Date())}] $msg"
def parseLog(def log){
def lines = []
new StringReader(log).eachLine{ line -> lines << line }
if(lines.size < 2) return;
def ret = [:]
def items = lines[1].split(/[|]/)
ret['rev'] = items[0].trim().substring(1)
ret['author'] = items[1]
ret['date'] = items[2]
ret['log'] = log
return ret
}catch (Exception e) {
return null
def getBASErev(def path){
def base = 'BASE'
"svn info -r BASE $path".execute().in.eachLine{
def m = it=~/Revision:\s+(\d+)/
if(m.matches()){ base = }
return base
projects.each{name, path ->
printLog("processing $name", ps)
def revisions =
"svn log -r BASE:HEAD --limit 30 --incremental $path"
def BASErev = getBASErev(path)
def lastrev = null
def logs = [['rev':'BASE']]
revisions.each{rev ->
def parsed = parseLog(rev)
if (parsed != null)logs << parsed
if(logs.size == 1){
printLog('already up to date, nothing to process', ps); return
def items = [];
for(int i =0; i< logs.size -1; i++){
def rev1 = logs[i], rev2 = logs[i+1]
if(rev2['rev'] == BASErev){ continue;} //no need to diff BASE
def diff =
"svn diff -r ${rev1['rev']}:${rev2['rev']} $path".execute().text
def s = SUBJECT.make([
rev: rev2['rev'], name: name,
author: rev2['author'] ]).toString()
def b = BODY.make([
name: name, rev: rev2['rev'],
author:rev2['author'], date: rev2['date'],
log: logs[i+1]['log'], fulldiff: diff
printLog( "changeset $s ...", ps)
items << RSS_ITEM.make(['subject':s, 'body':b,
'author': rev2['author'],
//here we assume the date is formatted as something like 2014-05-07 19:52:17 -0400 (Wed, 07 May 2014), which may not be true
//striping out the datestamp in parenthesis at the end
'date': rev2['date'].trim().replaceFirst(/[(].+?[)$]/, "").trim(),
'guid': UUID.randomUUID().toString() ]).toString()
lastrev = rev2['rev']
def outFileName = name.replaceAll(/\s+/, "_")+"_rss.xml"
new File(outFileName).withWriter{ out ->
<?xml version="1.0"?>
<rss version="2.0" xmlns:dc="" xmlns:itunes="">
items.each(){ item ->
//if everything finishes without problems
//bring the local to the last rev we had diffed
if(lastrev != null){
printLog("svn up -r $lastrev $path", ps) ;
"svn up -r $lastrev $path".execute() }
}catch(Exception e){
printLog('\nChilling out for 5 min ...\n', ps)
//chill out for 5 min
sleep chill*1000*60
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment