Last year there was a link to a blog post about displaying git info in your prompt floating around our office. We use Subversion at work so I whipped up a quick version for SVN. Nothing fancy, just a simple notification of when I’m sitting in a directory being tracked by SVN. Here’s the Bash code:
export PROMPT_COMMAND='_VC_LABEL= ;[ -d ".svn" ] && _VC_LABEL="[svn]"'
export PS1='\u@\h:${_VC_LABEL}\w$ '
which will produce something like
me@halley:~$ cd some-svn-dir
me@halley:[svn]~/some-svn-dir$
Love it or hate, Subversion makes this task pretty easy because each directory under its control contains a .svn sub-directory. So, all I have to do it check for the existence of .svn in the current directory. And voila.
Now, this weekend I took on the task of converting my personal Subversion repository over to Mercurial. I wanted to have similar functionality for directories under the control of Mercurial and keep the behavior for SVN as code from work is still in Subversion. Git and Mercurial both use a single control directory — .git and .hg respectively — in your project’s root directory. That means my simple method for Subversion wouldn’t work in this context; it would think you were in a version-controlled directory only if you were in your project’s root!
I took a look at the git-prompt project — which, from what I can tell, sprang out of the above-mentioned blog post — hoping to find a basis for Mercurial support. git-prompt is very full featured and even supports SVN beyond my simple implementation. However, one thing I didn’t like (besides not supporting Mercurial): It executes git/svn for every directory you enter. Ick.
So, my solution was to search up from the current directory looking for a .hg directory. If I find one only then do I execute hg to determine the branch info. Here’s the expanded version that supports both Subversion and Mercurial.
## Find a file or directory above current dir. Stops at /.
function hq_find_parents() {
local target="$1"
local newpwd=`pwd`
while [ 0 ] ; do
local lookfor="${newpwd}/${target}"
if [ "${newpwd}" == "/" ] ; then
return 1
elif [ -d "${lookfor}" ] ; then
return 0
elif [ -e "${lookfor}" ] ; then
return 0
fi
# Now "move" UP one directory.
newpwd=`cd ${newpwd}/..; pwd`
done
}
## Set _VC_LABEL based on version control system.
function hq_vc_label() {
if [ -d ".svn" ] ; then
_VC_LABEL="[svn]"
else
local _hg=`which hg`
if [ ! -z "${_hg}" ] ; then
hq_find_parents ".hg"
if [ $? -eq 0 ] ; then
_VC_LABEL="[hg:`${_hg} branch 2>/dev/null`]"
fi
fi
fi
}
_VC_LABEL=
export PROMPT_COMMAND='_VC_LABEL= ;hq_vc_label'
export PS1='\u@\h:${_VC_LABEL}\w$ '
Just add the above code to either .profile or .bash_profile and you’ll get something like this:
me@halley:~$ cd some-hg-dir
me@halley:[hg:default]~/some-hg-dir$