Thursday, May 12, 2005

The revison of "tags" in svn

In svn the idea of tags isn't the same as in CVS. To make a tag you in fact (simplified) make a copy of a revision and place it in the tags folder. This is to make it easy to get a tag as all you would have to do is checkout from the tag directory. But you could just checkout from trunk if you give it the correct revision number. If you have that revision number you can do a lot of interesting things such as determining what has changed sense the last release, see who made the most number of commits, or how many bugs were fixed (according to the svn commit logs). Unfortunately obtaining this revision number isn't that easy as you might think.

If you do svn info on the tagged directory you will find that it isn't the revision that was copied from, but a new revision and it doesn't have any properties. But this at least tells us something that we can use, the revision of the copy.  Using that version number we can get the full log for the copy with "svn log -r $rev -v ...". Note the "-v". If you don't pass -v then you won't see:

Changed paths: A /tags/source/phpquickgallery/phpquickgallery-1.7 (from /trunk/phpquickgallery:99)

Now pass --xml and you can easily and safely parse out the revision of the release (in this case 99). So after all that you finally have the trunk revision. :) The reason I originally wanted this piece of information was so that for my personal projects I could generate my ChangeLog file entirely from my svn commit log. My change log typically would have the exact same comment as my cvs commit log, but sometimes I wouldn't remember to add changes to the ChangeLog. So here is a little script which will generate a ChangeLog for a release

#!/bin/sh -x
# Gets the changes between two releases of an application
set -e

APP=$1
VER=$2
LASTVER=$3
HOST="https://foo.com/svn/src"
REP="$HOST/tags/source/$APP/$APP"

# Grep the version number of the move
rev=`svn info $REP-$VER/ | grep "Last Changed Rev" | sed s/Last\ Changed\ Rev:\ //g`
# Grep the log for the copyfrom revision (which is the real revision that this is taged from)
tag=`svn log -r $rev $REP-$VER -v --xml | grep copyfrom-rev | sed s/.*copyfrom-rev=\"//g | sed s/\"//g`

rev=`svn info $REP-$LASTVER/ | grep "Last Changed Rev" | sed s/Last\ Changed\ Rev:\ //g`
lasttag=`svn log -r $rev $REP-$LASTVER -v --xml | grep copyfrom-rev | sed s/.*copyfrom-rev=\"//g | sed s/\"//g`

# Get the log between the two versions
svn log -r $tag:$lasttag $HOST/trunk/source/$APP --xml > $APP-$VER.changelog.xml

# Grap the messages
# Remove empty lines and Internal messages
cat $APP-$VER.changelog.xml | awk '//,/<\/msg>/' | sed -e s/^\//g | \
sed -e s/\<\\/msg\>\$//g | awk ' !/^[ \t]*$/ { print $0 }' | grep -v Internal | \
awk 'BEGIN{print '$VER'} {print "* "$0}' > $APP-$VER.changelog

No comments:

Popular Posts