ColdFusion handling of Subversion events

I consider myself a casual user of Subversion (SVN). So every now and then I get surprised by what you can do with it. One of the cooler features of SVN is hook scripts. These are scripts that run based on SVN events, such as committing a file. As you can imagine this is a pretty powerful tool as it lets you have finer control and additional monitoring of your SVN repository.

So naturally the first thing I thought this morning was - How can I get ColdFusion hooked up to this?

Hook scripts are text files stored in the repository. To start using them you simply create the file. SVN provides samples for each of the events. On a Windows machine (where I was), you need to use actionname.bat or .exe for your file name. I wanted to write something that would fire after a commit action, so I created a file named post-commit.bat.

Now the question is - how do you run ColdFusion from a command prompt? Unfortunately there is no direct way of doing this. I took Ashwin's suggestion and downloaded Curl. Curl is a command line tool to download a URL.

Each hook script has different parameters passed to it. The post-commit script is passed the repository URL and revision number. In a bat file you can use these attributes as %1 and %2. Here is the bat file I used:

c:\progra~1\curl\curl.exe "http://127.0.0.1/testingzone/test.cfm?repos=%1&rev=%2"

So to recap - when I check a file into this repository, SVN will automatically fire off my bat file and pass in the repo URL and revision number.

So what did my ColdFusion script do? I could have simply sent an email with the information I was passed (repository and revision), but that isn't very helpful. I used SVN's command line tool to grab more information about the revision. Using CFEXECUTE I ran this command:

svn log file:///#repository# -r #revision# -v --xml

The log command simply returns the information about the revision. The -r attribute sets the revision to examine. The -v attribute tells SVN to verbose. Finally, and this is the coolest part, the --xml tells SVN to return the result in XML. Once I had the XML I had everything I needed to send out an email with the information about the commit action.

Before I paste the full ColdFusion code I used - a few notes. First off - Rob Gonda has some very cool Subversion wrapper code in ColdFusion. I bug him about once a week to release it as a project on RIAForge. :) I point it out to make the point that the code I used could have been done simpler with his API. (I know this as I use it at RIAForge and it has been very simple to use.) Secondly - SVN can return even more information then just a list of files. I could have also shown the diff in the email as well. Don't think you are limited to what I showed. Enjoy. If you actually use this code, let me know!

<cfparam name="url.repos" default="">
<cfparam name="url.rev" default="">

<cfif len(url.repos) and len(url.rev)>

   <cfset url.repos = trim(url.repos)>
   
   <cftry>
   <cfset svnexe = "c:\progra~1\subversion\bin\svn.exe">
   <cfset svncommand="log file:///#url.repos# -r #url.rev# -v --xml">

   <cfexecute name="#svnexe#" arguments="#svncommand#" variable="result" timeout="30" />
   <cfset resultXML = xmlparse(result)>   

   <cfset author = resultXML.log.logentry.author>
   <cfset msg = resultXML.log.logentry.msg>

   <cfset files = arrayNew(1)>
   
   <cfloop index="x" from="1" to="#arrayLen(resultXML.log.logentry.paths.path)#">
      <cfset thefile = resultXML.log.logentry.paths.path[x].xmlText>
      <cfset arrayAppend(files, thefile)>
   </cfloop>
   
   <cfmail to="ray@camdenfamil.com" from="svn@camdenfamily.com" subject="SVN Commit">
Repository: #url.repos#
Revision: #url.rev#
Message:
#msg#
      
Files:<cfloop index="x" from="1" to="#arrayLen(files)#">
#files[x]#</cfloop>
   </cfmail>

   <cfcatch>
      <cfmail to="ray@camdenfamil.com" from="svn@camdenfamily.com" subject="SVN HandlerError" type="html">
      <cfif isDefined("result")>
      result=#htmlcodeformat(result)#
      </cfif>
      <cfdump var="#cfcatch#">
      </cfmail>      
   </cfcatch>
   
   </cftry>
   
</cfif>

Comments

Jim's Gravatar Great post! I love SVN! Yesterday I was working on how to get it and ANT to write the revision # to my application.cfm.

Rob - cough up your scripts :)
# Posted By Jim | 12/9/06 3:31 PM
Sam Clement's Gravatar Very interesting stuff. Does this mean it is possible to use ColdFusion to create a full-featured Subversion interface? I've been wanting to do this but didn't think it possible...
# Posted By Sam Clement | 12/9/06 7:32 PM
Raymond Camden's Gravatar Sam, look at RIAForge. The SVN browser there is based on Rob's work. I just put the HTML on top of his CFCs.
# Posted By Raymond Camden | 12/9/06 7:40 PM
Rick O's Gravatar For those of you afraid of cfexecute but not afraid of installing a Java library, there's also Russ Johnson's Trac-Fu, which uses the JavaSVN library to talk to SVN:

http://tracfu.riaforge.org/

-R
# Posted By Rick O | 12/10/06 12:21 AM
Rick O's Gravatar For those of you afraid of cfexecute but not afraid of installing a Java library, there's also Russ Johnson's Trac-Fu, which uses the JavaSVN library to talk to SVN:

http://tracfu.riaforge.org/

-R
# Posted By Rick O | 12/10/06 12:22 AM
Edward T's Gravatar Ray, gotta note - the title needs an extra "u"....

otherwise, great, per always!!

Peace,
ejt
# Posted By Edward T | 12/10/06 8:32 PM
Raymond Camden's Gravatar Freaky. I didn't notice till this email came to me - and I saw it right away, and THEN I read your comments. :) Thanks!
# Posted By Raymond Camden | 12/10/06 8:35 PM
Ken Dunnington's Gravatar Automation is great :) I started playing with Ant recently, and in no time was able to whip up some very handy build scripts to package and deploy my apps. I'm planning on using something like this in the dev server I'm currently building - now if only I could convince other developers to actually leave commit messages!
# Posted By Ken Dunnington | 12/11/06 10:30 AM
Tuyen's Gravatar Are you trying to build an SVN API with coldfusion? I'm not sure why would you do that bc there are MANY VERY GOOD SVN API out there? I've been using SVN Tortoise (http://tortoisesvn.tigris.org/): as you might know it has some advantaged features over VSS....
# Posted By Tuyen | 12/11/06 10:45 PM
Raymond Camden's Gravatar Why would someone do that? To create a connection between CF and SVN. I agree Tortoise SVN is great. I use it. But CF can't use it - it is a Windows app that integrates with Explorer.
# Posted By Raymond Camden | 12/12/06 5:55 AM
Sam's Gravatar Ray,

Great stuff. I planned on taking some time this December to figure out how to do exactly what you've done. Now I don't have to, so thanks!

Now that you've figured out how to do it, are you going to make RIAForge projects update when someone checks in new code?
# Posted By Sam | 12/12/06 10:12 AM
Raymond Camden's Gravatar I'm considering it. First thing though is a basic "Subscribe to Project" feature for RIAForge. That will probably be next month.
# Posted By Raymond Camden | 12/12/06 10:17 AM
Collin's Gravatar First off, great stuff! We do something similar, on commit an XMPP message is sent to a conference room with the commit details and a list of files in the form of links to CFDIFF urls. We opted for IM over email to make the info more opt-in and the conference makes a nice place to discuss what is going on with the project.
The other half of the cf action updates a working copy for qa/testing. There are similar cf pages to 'deploy' to other locations. Some of the applications are very large (20,000 files, 2GB) so an export seems like overhead compared to a working copy. The cf pages currently use cfexecute to do updates and query the commit details. This works mostly but not all error messages are returned nicely and running the svn executable multiple times seems like it would be slower than using a sngle instance of the javasvn objects. I have worked with javasvn but not gotten the working copy client methods to cooperate. Are other people tackling the same issues or am I chasing the wrong solution and ANT or something is the better answer?
# Posted By Collin | 12/12/06 9:59 PM
Mike's Gravatar Added rough auto-update using svn update. We develop locally but have a remote dev server that designers and content management make changes to. Now when a commit happens the update appears on the remote server....

<!--- update --->
<cfset svncommand="update D:\inetpub -q --non-interactive">
<cfexecute name="#svnexe#" arguments="#svncommand#" variable="result" timeout="30" />
# Posted By Mike | 4/18/07 3:59 PM