Subversion Merge Change-log in 10 lines of Groovy

Problem. Bugs happen. The common solution to this problem is to fix the bug and release a patch. Version 1.0 has bugs, version 1.0.1 fixes those bugs.

Inevitably at some point in time you will need to put together a list of all of the changes in a release. For me, this needs to go into a format we can post on our wiki. This process can be tedious if it is a manual process. There are a few approaches to handling this. You can go against the bug tracking repository and look for what bugs were fixed for this release. This will tell you everything that should have changed. I say ‘should have’ here because you cannot know for sure if the information is 100% accurate.

The other option is to go to the version control repository for information on what has change. This is the authoritative source of what has changed but often contains more information than what you would want in a change-log.

In my previous post on version control I mentioned that we have best practices around format for commit messages. All bugs start with the words “Bug <number:“. A change-log can be constructed from these entries in subversion. I wrote a simple groovy script that generates this change-log for me. It uses the subversion command line interface. The starting point is using the ‘svn log’ command. This command generates a change-log. Here are the options used to this command:

  • The ‘–xml’ option is used to format the output as XML. This allows groovy to break it down easily.
  • The ‘-g’ option is used which shows log messages from other revisions that were merged onto this branch. Let’s say you have 50 bugs that are merged onto the bug fix branch all at once. This would create a single revision on the branch. Using this option includes all 50 comments from their original commit on the trunk. This detail we want in the change-log. This gives nested entries though so the code has to handle that case.
  • The ‘-r’ option is used to specify the revision range to use. In this case for a branch, we want from the previous release revision number to the current (or HEAD). For this example, let’s assume the 1.0 branch was at revision 1528.

The command to run then becomes:

svn log -r HEAD:1528 -g --xml

The next step that needs to be done is to take this XML and turn it into a change-log. I plan to use this as a comment into a wiki so I prefix the lines with ‘*’ so they will appear as a bulleted list in trac. It also puts the revision number at the end of the line in brackets. The output should look like this:

* Bug 123: Fixed some bug (1554)
 * Bug 126: Some other issue (1588)
 * Bug 322: Fixed the thing (1600)

To generate this changelog, I wrote a groovy script. It uses the svn command to generate the changelog and uses Groovy’s XML Parsing to break it up and format it. The path to the working directory and revision number would change from release to release but the rest of the code is reusable.

def handleEntry
handleEntry = {entry->
    def message = entry.msg.text()
    if (message.size() >= 3 && message[0..2].equalsIgnoreCase("bug")) {
        println " * $message (${entry.@revision})"

def proc = "svn log -r HEAD:1528 -g --xml".execute(null, new File("/path/to/working/directory"))
new XmlParser().parseText(proc.text).logentry.each(handleEntry)