Shell history, jigs, & subversion

Everyone else is showing theirs, so here’s mine:

$ history|awk '{a[$2]++} END{for(i in a){printf 5dt%sna[i],i}}'|sort -rn|head
  162   svn
   99   ls
   80   rtop
   69   sudo
   63   cd
   55   dotest
   51   workon
   23   make
   21   close_branch
   21   cl2svn

Software Jigs:

Does it say anything in particular about me that half of those commands are aliases or scripts I or my co-workers have created to wrap up other tools?

rtop – is a bash alias to change directory to the top of sandbox. I have an environment variable pointing there, too, but I guess I don’t like typing $.

dotest – is an alias to run tests with our tracing module turned on, preserving the output in the same log file each time. We have a very verbose trace module that prints function inputs and outputs as our program executes. It is superior to logging for low-level debugging, but entirely unsuitable for production use (it’s easy to turn on and off).

workon – is a shell function that swaps out different sandboxes so I can work on multiple branches on the same system. Our test framework requires an installed version of the whole system, unfortunately, and I don’t like to mix patches from multiple branches by copying files into the install tree. Running workon rearranges symlinks so I can replace the install tree with the build tree from my sandbox of choice. Shell functions are an under-appreciated implementation technique for something that has to operate on the current environment (workon changes directory to the new sandbox) but is more complicated than what would fit in an alias.

close_branch – is a bash script that takes a short branch name and deletes the branch and any “rebase” branches based on it using the long URL. We have a whole set of little scripts like this that we’ve written in house.

cl2svn – finds changes in ChangeLog files in my svn sandbox, extracts the new messages, and produces a single (sorted) output list formatted nicely to show up in trac. We use ChangeLog files and trac commit messages as part of the documentation for our code review process, so having everything formatted nicely is important. I used to do this by hand, but after one particularly large changeset I came up with this Python app to do the work for me.

Wrapping Subversion:

I mentioned close_branch as a subversion wrapper. There’s a make_branch script, too, to save from making typos in long URLs.

Another shell function, mksbox, finds a free sandbox in my pool and switches it to use a particular branch. Our build tree is pretty large, so it is way more efficient to just keep a bunch of sandboxes around and switch them to point to different branches with svn switch instead of checking out a full copy every time.

My favorite, though, is merge_branch, which figures out the start point of an svn branch and merges all of the changes from that branch into the current sandbox. I’m a little surprised that make_branch and merge_branch didn’t show up higher in the list, but they’re in the top 20.

We wrote these wrapper scripts a couple of years ago, when we switched from CVS to svn. We had similar tools for CVS, but branching worked differently and we didn’t use branches as often then. Now every ticket gets its own branch, so managing branches is a daily operation. A typical development cycle for me looks something like this:

$ make_branch 6583 # that's a trac ticket number
$ mksbox 6583 # automatically does a workon for that sandbox
$ dcctl restart # restart our daemon services to pick up the sandbox change
# add feature or remove bug
# update ChangeLog files
$ cl2svn | tee changes.txt
$ svn commit -F changes.txt
# request code review for changeset
$ # switch current sandbox to trunk & merge in the branch
$ docommit # commit, using the first line of changes.txt for log message
$ close_branch 6583 # clean up after myself

When we switched off of CVS, we had some particular needs that weren’t met by svn directly (especially the way we do code reviews). There are a whole host of tools for wrapping svn out there now. sv-subversion looks interesting, but I haven’t tried it. If our code didn’t make assumptions about the install path, we could probably just use DivmodCombinator, which looks like it has a lot of the features we’ve rolled ourselves, but the inertia for changing now is pretty high, and the benefits aren’t great enough.