On Subversion

I’ve recently started using the Subversion Source Control system a lot more. It really has got pretty stable now and I feel happy about telling people that they should consider migrating to Subversion from CVS (or in fact pretty much any other Source Control tool) as soon as they can. Atomic checkins, offline features, scalibility, useful and easy tags and branching, and lots of other good stuff all make it a compelling tool.

One thing that has helped Subversion recently is the improved documentation available. An example of this is Mike Mason‘s new book Pragmatic Version Control Using Subversion. I have to say right now that I’m an old friend and colleague of Mike’s and also reviewed the book, so I am completely biased, but I think its a brilliant tutorial to getting started with Subversion, and a handy reference to have around.

Mike’s also recently helped me out with a couple of things that weren’t in the book, so I wanted to share them here.

Firstly, if you’ve been following my blog recently you’ll know I’ve been using Cygwin a lot more. One of the things that Mike does very well is show how powerful and easy the svn command line client is. I was using the standard Windows download of Subversion with Cygwin, but apparently this is a really bad idea. Apart from not using the right kind of paths, you can apparently also get file corruption.

Anyway, this is easy to change – open up the Cygwin installer and choose to use its version of Subversion – its in the devel folder. Cygwin will automatically update your path so that your Cygwin version of svn is used rather than the previous one you installed. You’ll also need to repeat any changes you made to your Subversion config file – the Cygwin version will appear in the ~/.subversion/ directory. If you’ve already setup Putty, Plink and Pageant to manage your SSH identity this will still work – my config file has one change to support this:

[tunnels]

ssh = $SVN_SSH /c/tools/putty/PLINK.EXE

The second thing is to do with deletes. During the course of a development episode, I might well delete some old files. When I perform a svn status I will get a bunch of files showing as ! meaning that they have been removed by something other than a Subversion request. In fact I’ll get output a bit like this:

$ svn st

A      src/Core/Generators/NewGenerator.cs

!      src/Core/Generators/StandardDotNetUpperCaseGuidGenerator.cs

!      src/Core/Generators/IGuidGenerator.cs

Typically I then manually run a svn rm command for each of these, but this can get a little tedious after you’ve done it once. So since I’m using Cygwin, I can use some script to get the shell to do it automatically for me:

$ svn st | awk '$1 == "!"' | cut -c 2- | xargs svn rm

D         src/Core/Generators/StandardDotNetUpperCaseGuidGenerator.cs

D         src/Core/Generators/IGuidGenerator.cs

Now I don’t want to have to remember to do this every time, so I add this to the .profile file in my Cygwin home directory:

alias svnrmdeleted='svn st | awk "$1 == \"!\"" | cut -c 2- | xargs svn rm'

Now to remove from Subversion all deleted files I just type svnrmdeleted .

UpdateMatt Ryall came back with the update to the above using awk rather than grep. (Otherwise you might end up deleting files with actual “!”‘s in the name). He also grappled the required escaping to get the alias to work. (Thanks Matt!)

Update – Dan Bodart has since told me how to do this in plain Windows shell (Thanks Dan!):

  • for /f "usebackq tokens=2" %i in (`"svn st | findstr !"`) do svn rm %i

So, in summary – go use Subversion! Even if you are mostly a Windows user then try using its command line and ask some friendly UNIX- (or Windows Script-) savvy people how to automate some things you do often.

Automated SSH authentication on Windows

I use a few remote UNIX servers. Some host web content, some are Source Control repositories. All of them I access using SSH either for an interactive shell, or as a tunnel for applications like Subversion, CVS or rsync.

A few months ago when I started committing to projects on Codehaus I had to setup a SSH key-pair since they don’t allow plain password authentication for their SSH server. This was actually good since I’d been meaning to switch to key-based authentication for a while but hadn’t quite got around to it. The main reason for using key-pairs is the extra security – you have to ‘bring something’ (your private key) as well as just ‘know something’ (either a password, or the passphrase of your private key). However there is an added benefit in using key-pairs in that once you have set them up once in any one ‘session’ you don’t have to keep re-entering a password. (A session here is usually a Windows, or X-Windows, login session.)

It took me a while to get all of that setup though. I wanted to use Putty since it was before I’d started using the command line in anger. Putty actually makes this kind of thing pretty easy through using its Plink (RSH implementation), PuTTYgen (Key generator) and Pageant (key authentication agent) programs, but the problem was around key formats. Putty by default saves you a public key that won’t work on an OpenSSH remote server. After some head banging and half an hour with a friendly CodeHaus Despot or two on an IRC channel and we managed to get it working. The key (haha!) was to do the following in PuTTYgen:

  • Use SSH2 DSA keys
  • Don’t use the public key file that is saved, but instead use the contents of the box at the top of the window. Yes, the one that says ‘Public key for pasting into OpenSSH authorized_keys file’ that I should have used straight away 🙂

Then it was just a matter of setting up a saved Putty session (including my user name) and adding my key to Pageant. You do have to remember to try to use Putty for an interactive login the first time you connect to a server so that it can save a copy of the server’s key locally.

Using Plink works fine for command line Subversion (see my earlier post for my [tunnels] setup), but today I hit a problem using it with rsync. Cygwin’s rsync seems to want to use Cygwin’s ssh, and Plink just doesn’t seem to play ball. ‘No problem’, I thought, ‘UNIX must have an equivalent of Pageant’. Indeed it does – its called ssh-agent. Using this helpful page I found the required incantation, but hit a problem in that it wouldn’t accept the passphrase on my private key. After a couple of minutes I realised that it was another formatting problem which PuTTYgen could solve for me. All up then, being able to use my Putty-generated private key on Cygwin required the following steps:

  • Load private key in PuTTYgen
  • From the Conversions menu, select Export OpenSSH key
  • Save it as a file called id_dsa in the ~/.ssh directory. On my machine that is equivalent to c:\Documents and Settings\mroberts\.ssh\id_dsa
  • Add the following to my ~/.profile file : alias startssh="eval \`ssh-agent\` ; ssh-add"
  • Add the following to my ~/.profile file : alias stopssh="ssh-agent -k"

Now I just run startssh and stopssh around any times I want to do some rsync work. Its not perfect since right now I need to startup ssh-agent for every Cygwin prompt, and I also need to stop it before I exit the prompt otherwise the window will hang. There’s probably some hackery that can be done using a Windows Service, but I’ll save that investigation for another day.