Raven Examples - Subversion On-Commit Email

Subversion On-Commit Email

The generic post-commit Perl script that came with Subversion sends a normal plain text email displaying repository information, revision number, log message, file list, and a diff dump of each file. I find this quickly becomes hard to read when the emails get large. Listed here is a script to create a HTML email of similar layout with a little extra formatting to:

  • colour added file names and lines blue.
  • colour deleted file names and lines red.
  • separate files with horizontal rules or place them in <div> with CSS for readability.
#!/usr/local/bin/raven 
 
time 
 
# ARGS holds a list of arguments pulled from the command line. 
ARGS 2 get as $path 
ARGS 3 get as $revision 
ARGS 4 get as $emailto 
ARGS 5 get as $emailfrom 
 
$path '/' split pop as $project 
 
'/usr/bin/svnlook' as SVNLOOK 
 
'/tmp' chdir 
 
# Execute subversion shell command. 
define svn_cmd use $cmd 
	[ SVNLOOK $cmd $path '-r' $revision ] 
	BL join shell trim 
 
# Build list of trimmed lines. 
define svn_array use $text 
	$text LF split as $list 
	$list each rtrim drop 
	$list 
 
# Filter HTML special characters from text. 
define html_safe 
	'&amp;'  '&' replace 
	'&lt;'   '<' replace 
	'&gt;'   '>' replace 
	'&quot;' '"' replace 
 
# Encapsulate and colour a string. 
define colour_xxx use $text , $colour 
	'<span style="color: #' $colour . ';">' . $text . '</span>' . 
 
# Modified lines. 
define colour_mod 
	'009900' colour_xxx 
 
# Deleted lines. 
define colour_del 
	'DD0000' colour_xxx 
 
# Added lines. 
define colour_add 
	'0000DD' colour_xxx 
 
'info'         svn_cmd svn_array as $svn_info 
'dirs-changed' svn_cmd svn_array as $svn_dirs 
'changed'      svn_cmd svn_array as $svn_changed 
 
# Diff the files. 
'diff' svn_cmd html_safe svn_array as $svn_diff 
 
$svn_info shift as $author 
$svn_info shift as $date 
$svn_info shift drop 
 
[ ] list as $adds 
[ ] list as $dels 
[ ] list as $mods 
 
# Break out lines into lists according to their state. 
$svn_changed each copy 
	dup '^A' match 
	if	$adds push 
		break 
	dup '^D' match 
	if	$dels push 
		break 
	$mods push 
 
# Begin building the email streaming lines of text onto the stack. 
[ '<pre style="color: #000000;">' 
'Repository: '   $path . 
'Author: '       $author . 
'Date: '         $date . 
'New Revision: ' $revision . 
BL 
 
define bold_text 
	'<b>' swap . '</b>' . 
 
define chop_flag 
	4 over length extract 
 
$adds empty not 
if	'Added' bold_text 
	$adds each chop_flag colour_add 
 
$dels empty not 
if	'Deleted:' bold_text 
	$dels each chop_flag colour_del 
 
$mods empty not 
if	'Modified:' bold_text 
	$mods each chop_flag colour_mod 
 
BL 
'Log:' bold_text 
$svn_info each 
BL 
 
# Usual diff deal. 
# Lines starting with '+' are new and '-' are old. 
$svn_diff each as $line 
	$line '^\+' match 
	if	$line colour_add 
		break 
	$line '^-' match 
	if	$line colour_del 
		break 
	$line '^(Modified|Added|Deleted)' match 
	if	'<b>' $line . '</b>' . 
		break 
	$line '^=====' match 
	if	'<hr>' 
		break 
	$line 
 
'</pre>' 
 
# Implode the lines accumulated on the stack since '['. 
] CRLF join as $content 
 
[ 'From: SVN ' $author  . ' ' . 
  'Subject:  ' $project . ' r' . $revision . BL . $svn_dirs BL join . 
  'To:       ' $emailto . 
  'Content-type: text/html' ] 
CRLF join as $headers 
 
# 'mail' merely pipes data to the sendmail binary. 
$headers $content mail 
 
time swap - "%d seconds\n" format print
Get Firefox!