Using the Subversion Ruby Bindings

September 19, 2007

I work with a distributed team of Ruby (on Rails) developers, and we use Subversion as our repository of choice. Just recently, I wanted to find out which files were recently changed or added to a particular directory of our project.

Doing it manually would’ve been tedious. I also wanted to do it with code so that maybe sometime in the future we might be able to script some behavior depending on the last changed date of a file or group of files in our repository.

I could’ve resorted to merely calling svn info and parsing its output, but I thought maybe this was a good excuse to sharpen my Ruby chops and figure out the Subversion Ruby bindings.

Obtaining the Subversion Ruby Bindings

Subversion has shipped with Ruby bindings since 1.3. You can build Subversion from scratch, and then build Swig then the Ruby bindings like so.

Or, if you’re on the Mac and use MacPorts like me then it’s all much, much simpler. If you don’t have Subversion yet, you can install it using

sudo port install subversion +no_bdb

The +no_bdb variant instructs MacPorts to build Subversion without the Berkley DB back-end. This is necessary because as of this writing I kept running into issues when MacPorts attempts to build db44 , which apr-util depends on. If you have to use the BDB filesystem with Subversion, then see my previous entry to build db44 first, then you can build Subversion normally with just sudo port install subversion.

Once you have Subversion installed, it’s just another simple matter to get the ruby bindings:

sudo port install subversion-rubybindings +no_bdb

Again, note the +no_bdb variant. Now, maybe there’s a way to instruct MacPorts to build Subversion with the Ruby bindings in one command that I don’t know of. In any case, the above command alone works if you already have Subversion installed.

Poking around…

At this point, I thought I was all set to use the Subversion Ruby bindings. Firing up irb and going require 'svn/core' returned true so I thought I was well on my way.

Unfortunately, I had to do a little more poking around to actually figure out how to get it to work. First off, I couldn’t find any handy reference to the Subversion Ruby API. For this, your best bet is the actual source which you can view here.

Diving into the source can be intimidating (and a put off) for some people, but fortunately Ruby code is quite easy to read and comprehend (one of the reasons why I like it). Unfortunately, the Ruby code itself at times just drops down to the actual Subversion C APIs. Fortunately, we can find a reference for those APIs via the Subversion doxygen-generated documents here.

Displaying Subversion file information using Ruby

Armed with the above, I was able to put the pieces together. The following is a simple script that mimicks the output of svn info on a Subversion working copy:

#!/usr/bin/env ruby
require 'svn/client'

# Get the first argument from the command line
target = $*[0]

ctx = Svn::Client::Context.new

receiver = Proc.new do |path, info|
  puts "Path: #{path}"
  puts "URL: #{info.url}"
  puts "Repository Root: #{info.repos_root_url}"
  puts "Repostiory UUID: #{info.repos_UUID}"
  puts "Revision: #{info.rev}"
  puts "Node Kind: #{info.kind}"
  puts "Schedule: #{info.schedule}"
  puts "Last Changed Author: #{info.last_changed_author}"
  puts "Last Changed Rev: #{info.last_changed_rev}"
  last_changed_time = Time.from_apr_time(info.last_changed_date)
  puts "Last Changed Date: #{last_changed_time}"
end

Svn::Client.info(target, nil, nil, receiver, false, ctx)

A little note, at first I was simply calling ctx.info(target) {|path, info| ...} like what might be inferred from the test code. This works, but will prompt for the Subversion authentication (SSH, actually, since we use “svn+ssh:” repository URLs). I figured out from the API documentation that you have to pass NULL (or svn_opt_revision_unspecified, which I couldn’t find the Ruby constant for) to force the Subversion client to pull the information solely from the working copy.

Now that we can at least view the working copy information, the rest of the bindings should be useable with the source, the unit tests and the API docs as references.

Happy hacking!

Advertisements

2 Responses to “Using the Subversion Ruby Bindings”

  1. Nico Says:

    Interesting post. Have you played around with the bindings anymore ?


  2. […] described in Using the Subversion Ruby Bindings there are official Ruby-Subversion bindings. They’re huge and for my simple Subversion backup […]


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: