ColdFusion and Subversion

This post is more than 2 years old.

A few days ago I asked on the BlogCFC blog about a way to display a report from Subversion. I knew how to get a report of the latest updates for one file, but not for a project as a whole. A few people recommended Trac, but being the kind of guy I am, I wanted to build something myself.

Scott P (who has contributed some good changes to BlogCFC) told me what the SVN command was:

svn log -v svn:// --limit 10

This command will give you a nice report of the last ten changes to the subversion repository. I was about to hook this up to CFEXECUTE and start writing a string parser when I had the brilliant idea of actually checking the documentation. Turns out if you add --xml to the command, you actually get the report back in XML:

svn log -v svn:// --limit 10 --xml

No string parsing necessary! So I quickly whipped up some code (included below) and added the report to BlogCFC. You can find the SVN info here:

Nice design, eh? Hard to believe I'm just a developer. The code is a work in progress, and not encapsulated into a CFC, but for those who want to add this to your site, I've included it below. Some notes:

  • I'm not parsing the dates yet. It's UTC, so I just need to add the offset which I can get from getTimeZoneInfo().
  • You could make the files linkable if you wanted, but you always need to be extra-super-anal-etc when writing code that will dump another file live on the web. In fact, I'd probably just not recommend doing this unless the entire application is very secure.
  • SVN also reports what happened to the file. So for example, I think it uses M to signify that the file was modified. I bet it uses A for Add and D for Delete, but I haven't confirmed this. I'd like to update my code to not just show the files but what the change was.
  • And as I said above, this should be rewritten into a little UDF or CFC.
<!--- path to svn ---> <cfset svnPath = "svn">

<!--- whats the url? ---> <cfset svnURL = "svn://">

<!--- how many entries ---> <cfset top = 10>

<!--- args ---> <cfset args = "log -v #svnURL# --limit #top# --xml">

<!--- run it ---> <cfexecute name="#svnPath#" arguments="#args#" variable="result" timeout="30" />

<!--- parse to xml ---> <cfset data = xmlparse(result)>

<!--- get entries ---> <cfset entries = xmlSearch(data, "//logentry")>

<cfset logEntries = arrayNew(1)>

<cfloop index="x" from="1" to="#arrayLen(entries)#"> <cfset entry = entries[x]> <cfset logEntry = structNew()> <cfset logEntry.revision = entry.xmlAttributes.revision> <cfset logEntry.files = arrayNew(1)> <cfloop index="y" from="1" to="#arrayLen(entry.xmlChildren)#"> <cfset xmlChild = entry.xmlChildren[y]>

	&lt;cfswitch expression="#xmlChild.xmlName#"&gt;
		&lt;cfcase value="author,msg,date"&gt;
			&lt;cfset logEntry[xmlChild.xmlName] = xmlChild.xmlText&gt;

		&lt;cfcase value="paths"&gt;
			&lt;cfloop index="z" from="1" to="#arrayLen(xmlChild.xmlChildren)#"&gt;
				&lt;cfset thisFile = xmlChild.xmlChildren[z].xmlText&gt;
				&lt;cfset arrayAppend(logEntry.files, thisFile)&gt;

&lt;cfset arrayAppend(logEntries, logEntry)&gt;	


<cfdump var="#logEntries#">

Raymond Camden's Picture

About Raymond Camden

Raymond is a developer advocate for HERE Technologies. He focuses on JavaScript, serverless and enterprise cat demos. If you like this article, please consider visiting my Amazon Wishlist or donating via PayPal to show your support. You can even buy me a coffee!

Lafayette, LA