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
$ prepare4commit.sh # 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.