Since I published Mercurial current branch in your Bash prompt in April, I’ve made some improvements.
The first is that, in a freshly initialized Mercurial repo, reporoot/.hg/branch isn’t written, so fasthgbranch doesn’t find anything. The fix for this is simple: just output “default” if you find a Mercurial repo, but no branch file.
The second is that it now works on Mac OS X (and probably, by extension, *BSD). I recently got a programming job (where we use Mercurial!), and my work computer is a Mac. Porting to OS X involved two changes. Firstly, I had to replace the Linux-only system call get_current_dir_name() with the equivalent getcwd(NULL, 0), which is also a Linux extension to POSIX, but happens to work on OS X too. Secondly, OS X sed behaves slightly differently from GNU sed. GNU sed supports both “&” and “\0” to mean “the entire match”, while OS X sed only supports &.
All of these improvements have been reflected in the original article.
Edited 2011-06-17: Added Mac OS X support
(Make sure to read the whole thing; my first solution is slow and will cause pain and anguish for the user.)
So I thought it’d be useful to have the current branch of a local Mercurial repository in my bash prompt. This is easy enough, because we have hg branch. The result:
PS1='\u@\h:\w$(hg branch 2> /dev/null | sed "s/.\{1,\}/ [hg:\&]/")\$ '
Basically, it tries to grab the current branch, discards any error, and then sends the results off to sed. The sed script basically says “if there’s at least one character (i.e. a repo was found), put it into the format [hg:branchname], otherwise return nothing”.
The result:
jonathan@kippersnacks:Code/active/awesomeproject [hg:default]:
It works perfectly, except for one thing.
It’s a bit slow. As in perceptibly slow. As in irksomely slow.
Mercurial is not the speediest of version control systems, and this command is no exception. While the delay is acceptable for commits, pushes, and pulls, it is not when attempting to display a bash prompt. One may choose to blame this on Python, but that’s sort of irrelevant.
Well, it turns out that the name of the current branch is stored in reporoot/.hg/branch. This is terribly convenient, as we can just cat it—oh wait. We also have to recurse up through directories. I’m sure this is quite possible in bash, it’s just it would be rather unwieldy, and possibly evilslow. And I’m not a bash wizard.
Git is quite fast, and has a similar tool for this very purpose—written in C of course. So I took a few minutes to dash off a C program which does the job in about 50 lines. You can find it here: http://sleepingcyb.org/downloads/fasthgbranch.c
Compile it with gcc -o fasthgbranch fasthgbranch.c, put it in your $PATH, and use something like
PS1='\u@\h:\w$(fasthgbranch | sed "s/.\{1,\}/ [hg:\&]/")\$ '
as your bash prompt in ~/.bashrc (or ~/.bash_profile if you’re on OS X).
Lightning fast.
It’s basically public domain, and you can do whatever you want with it, so enjoy. If you republish or redistribute it, it’d be nice if you credited me, but I don’t mind too much if you don’t for some reason. If you take credit for it yourself you are an evil scumbag plagiarist but there really isn’t much I can do about that.