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>
Archived Comments
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 :)
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...
Sam, look at RIAForge. The SVN browser there is based on Rob's work. I just put the HTML on top of his CFCs.
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
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
Ray, gotta note - the title needs an extra "u"....
otherwise, great, per always!!
Peace,
ejt
Freaky. I didn't notice till this email came to me - and I saw it right away, and THEN I read your comments. :) Thanks!
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!
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.o... as you might know it has some advantaged features over VSS....
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.
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?
I'm considering it. First thing though is a basic "Subscribe to Project" feature for RIAForge. That will probably be next month.
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?
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" />
Does anyone know of or have a ColdFusion SVN API where a more complete set of SVN commands are included in a single CFC wrapper?
I'm want to build a web interface to a SVN working copy on a test server.
Paul Cormier
I see 7 projects when I search for SVN in the CF category at RIAForge:
http://www.riaforge.org/ind...
This post just saved me a crap ton of reading and time, thanks! Looks like there are no hooks for identifying update events, which makes me sad. But the post commit is still freaky sweet.
Always makes me feel happy when old posts like this are still useful. :)
Holy crap - I just looked at the date... 2006. Almost 6 years old!