Tag Archives: subversion

svn get revision

One of the more annoying things about svn is that (to my knowledge), there exists no single simple command to retrieve the revision number from a shell.

What I want:
[code]
ammon@hermes:~/repo$ svn info –get-revision .
1234
[/code]

But of course, nothing like this exists.

Thankfully, svn info’s output IS easy enough to parse. You just have to do it your self.

[code]
ammon@hermes:~/repo$ svn info | grep Revision | awk — ‘{print $2}’
1234
[/code]

Will give you the revision of your current checkout without the network hit of a call to svn log.

To get the current version of the repo itself (hits the network), add “-r HEAD” to the svn info call:

[code]
ammon@hermes:~/repo$ svn info -r HEAD | grep Revision | awk — ‘{print $2}’
1280
[/code]

Of course, svn info also supports outputting info as xml, so you could use that to parse things in a more advanced environment but one where you’re still not using the svn api bindings.

svn whitespace blues

For the longest time, I have been suffering with problems of changes whitespace rendering SVN diffs useless.

Sometimes it’s the spaces vs tabs issue. Sometimes it’s file line endings (silly Windows-only editors and their CRLF). And sometimes it’s just people adjusting whitespace arbitrarily on lines (like adding spaces around parens or leaving spaces at the end of lines, etc…).

Regardless of the individual manifestation, it’s a silly problem, but one that causes more than its share of tears among developers everywhere.

Perhaps the easiest and smartest solution is to browbeat your co-developers into compliance. Force people to use editors that preserve line endings, force them to strip trailing whitespace and conform to a universal standard of indentation, etc… but it’s not always the nicest or most reliable solution. People will make mistakes, even if it’s only once a month… going over that diff might cost you an hour to figure out what had actually changed.

There are a few other solutions out there. They’re not new, and they’re not for everyone… but they can be phenomenally helpful at times. I’ll go over the two simplest ones.

dos2unix

Ever gotten a diff that reads like this?

This is what happens when something changes the line endings of a file. In this case, the original file was created with LF endings and was then edited slightly by an application that converted them to CRLF.

Now… if this were a 1000 line perl script in stead of an 11 line lyrics snippet… it would be soulcrushingly difficult to find the one actual change in the file.

Most unix distros have at their disposal the dos2unix / unix2dos utilities. On Red Hat, you can yum install dos2unix to get them. On Debian/Ubuntu, you can apt-get install tofrodos. I don’t have any other unices lying around at present to check on, but you can always just get the source at http://www.thefreecountry.com/tofrodos.

Much easier to figure out what has changed this way.

For extra credit, look into the svn:eol-style property. Set this on files as you commit them – or just use autoprops to do the dirty work for you…

diff-cmd

Of course, some times it’s not line endings. Sometimes the problem is random meaningless whitespace changes. Maybe somebody used an editor that auto-indents with spaces when the file was already indented with tabs, etc…

Subversion allows you to specify an alternate command to use to generate your diffs (in stead of relying on svn’s internal diff generation).

But what if (for some bizarre reason) you don’t care about the case of letters?

If you always want to use your custom diff utility you can set it in your runtime config to save yourself the hassle of having to type it manually each time.

For those using TortoiseSVN, you can always just specify graphical diff/merge utils to use in stead of Tortoise’s builtin ones. Personally, I’m a big fan of WinMerge, but there are several other good ones out there.

ant + svn = love

Back in December, I built a system where my SVN post-commit hook automatically updated a file containing revision info for an application I’m writing.

Well, a few things got shuffled in our ant buildfile and that script stopped working. Not because it was bad… just because files moved around and nobody thought to update it.

My group is currently moving away from allowing Flex Builder to handle our compilation and to just using ant on both dev workstations and for server-side deploys. This got me fiddling with ant a bit more this morning and resulted in my stumbling across the SvnAnt ant task. A bit more fiddling, and I now have ant generating the version.xml files for us at build/deploy time in stead of relying on the shell script.

SvnAnt is cool. It can perform most svn operations for you from within your ant builds. This means you could automatically push builds to a server or use ant to expedite the creation of new repositories, or whatever.

My adventures with SvnAnt have born two neat little toys:

  1. I now have a build target that automatically updates both the current repository AND my classpath repository (in case I forget to poke one or the other).
  2. I also have a build target that extracts revision versions and builds my xml data file for me. No more stale files on the dev side of things and the ant version is much more robust – it works even when we move files around 🙂

installing svnant

I downloaded SvnAnt and dumped the jar files into a /lib dir in my repository. This simplifies builds tremendously if the jar files are always kept close to the build.xml file.

I added a few lines near the beginning of my buildfile:

This loads the jar files and preps the <svn/> tasks for use.

update_and_build

This calls the svn update first and then continues on to execute the normal build (where “build_all” is a valid target, of course).

In my case, I have a classpath repository that I also want to update when performing this target. The location of my classpath is defined as as3ClassPath in my build.properties file, so I just add <update dir="{as3ClassPath}"/> to my svn tag, then it updates both repos for me if needed.

make_version

The version.xml generation code is likewise very painless to use.

Note that I use $$’s to escape the $’s in my output and that I use html entity codes for my >/< chars.

The result is that every time I run the build, we get a file called version.xml containing xml that (if indented for human readability) looks something like:

So… I like it. It makes me happy. There’s a lot more that the ant task can do. Take a look at the docs for more info.

update

So… it appears that sometimes the SvnAnt stuff isn’t behaving quite as well as it should. Namely, it fails to use the java svn interface that I thought was being included in the svnjavahl.jar file in the package… but apparently not.

If you have this problem, just make sure you have a modern version of the svn cli utilities installed. For those of you running windows + TortoiseSVN, this just means you’ll also need to download and install svn-1.4.3-setup.exe or whatever the current version may be at the time of reading 😉

If that doesn’t work, well, I’ve figured out how to make the thing work w/the JavaHL interface. Download svn-win32-1.4.3_javahl.zip (or current version, of course), and drop the dll contained in the zip file into your C:\Windows\System32 folder. Then restart your IDE, and voila.

svn keyword magic

Subversion is officially the coolest thing ever 😉

And now on a related note…

Yesterday during a code review, the svn:keywords property was discussed, and the idea proposed to start using it to embed magical versioning information into our builds (for bug reporting reasons and such). Well, I decided to jump on the idea this afternoon. After a bit of fiddling, we now have a little component that can be used to display the revision number of the current application build – all w/o anyone having to remember to do it.

The SVN Book explains how to use the property in greater detail.

I created a simple xml file (it could be any text file, really), that I then dropped the svn keyword tags into it.

I then set the svn:keywords property on the file to “Date Rev” (ie, the names of the keywords i want replaced – see the full docs for a list of valid keywords).

Upon commit, the file is updated on the server to now look more like this:

Unfortunately… there’s a major hitch in what I wanted to do. These labels actually only update when the file in question is updated. Ie, it displays the last time the source file was changed, not the last time the entire repository was changed. So, this trick is useful for updating header comments or perhaps an internal version constant string (if you’re doing server-side post-commit builds or something). But… it’s not what I want in this case 😉

In the end, I wound up having to do a bit of old fashioned sed manipulation on the server side post-commit… but that doesn’t change the fact that subversion still allows me to do this kind of magic. It’s just not quite as magical as I’d originally hoped it could be.

My post-commit hook now looks something like this:

I’m keeping updated copies of a part of the repository in a web accessible directory, and am using Ant to build deployable zip files and such. The sed commands are performing a search and replace on the svn keywords before the build and I then revert the changes (just in case somebody actually changes the real contents of version.xml – which would result in a conflict if we kept these local changes around).

The file I’m producing now looks like this:

If I really wanted to, I could generate the same exact date format as SVN uses, but I prefer this one for its brevity.