Archive for May, 2010

My Mercurial Prompt

This has come up a few times and so I thought I would post this. I use Steve Losh’s hg-prompt extension and I have it configured so that it displays the revision and the patch number if I am using Mercurial queues: Like so:

My Mercurial Prompt

To get this paste the following into your .bashrc file:

############################################################################# # Set up Prompt ############################################################################# noColor='\[\033[0m\]' blackColor='\[\033[0;30m\]' redColor='\[\033[0;31m\]' greenColor='\[\033[0;32m\]' yellowColor='\[\033[0;33m\]' blueColor='\[\033[0;34m\]' purpleColor='\[\033[0;35m\]' cyanColor='\[\033[0;36m\]' greyColor='\[\033[0;37m\]' boldGrayColor='\[\033[1;30m\]' boldRedColor='\[\033[1;31m\]' boldGreenColor='\[\033[1;32m\]' boldYellowColor='\[\033[1;33m\]' boldBlueColor='\[\033[1;34m\]' boldPurpleColor='\[\033[1;35m\]' boldCyanColor='\[\033[1;36m\]' boldWhiteColor='\[\033[1;37m\]' # Change the prompt to be user@host:path$ with some colors # simple version would be say # export PS1="${noColor}[${yelloColor}\h${noColor}:${greenColor}\w${noColor}] \$ " # Function that returns the last n path components of the specified path after # replacing $HOME with ~. Call like: # pathComponents path n nameColor seperatorColor function pathComponents { echo `python -c\ "import string,re; pth=re.sub('^$HOME','~',r\"$1\",1); n = string.atoi(r\"$2\"); nc=r\"$3\"; sc=r\"$4\";\ print nc + string.join(pth.split('/')[-n:], sc + '/' + nc);"` } # this is my mercurial prompt. It relies on the hg-prompt extension : http://stevelosh.com/projects/hg-prompt/ # its basically: basename rev(tip) on branch at bookmark patchnum#/patchcount# hg_ps1() { # hg prompt "{ on ${greenColor}{branch}${noColor}}{ at {bookmark}}" 2> /dev/null hg prompt "${cyanColor}{root|basename}${noColor}\ { ${blueColor}{rev}${greyColor}}\ {(${cyanColor}{tip}${greyColor})${noColor}}\ { ${greyColor}on:${cyanColor}{branch|quiet}${noColor}}\ { ${greyColor}at:${noColor}{bookmark}${noColor}}\ { ${greyColor}mq:${purpleColor}{patch|applied|quiet}${noColor}}{/${purpleColor}{patch|count|quiet}${noColor}} " 2> /dev/null } #export PS1='\u at \h in \w$(hg_ps1)\n$ ' function myPromptCommand { local newPWD=`pathComponents "\${PWD}" 4 \${blueColor} \${redColor}` # the trimed colored path echo -ne "\033]0;${HOSTNAME%%.*}:${PWD/$HOME/~}\007" # this sets the title export PS1="${noColor}[${greenColor}\h${noColor}:${newPWD}${noColor}] $(hg_ps1)⌘ " } PROMPT_COMMAND=myPromptCommand # Change the title of each window, and PS1 to reflect where we are

Leave a Comment

Versioning your application with the Mercurial changeset hash

A user of MacHg (Marko Käning) wanted to be able to see the changeset hash in the About MacHg box (see here). I had been meaning to do this at some stage and, well, given the request, now seemed as good a time as any… It turns out it was quite easy to configure XCode to create the appropriate information while building MacHg.

(In my workflow I release versions of MacHg every so often, and I want users who get the source code off of bitbucket and build it for themselves to be able to easily tell me something like “In such and such a version of MacHg I am seeing XYZ happen.”)

So now MacHg shows the following sort of thing when you look in the About MacHg box (note the grayed c0d2f1df774d hash code):

ok so how did I go about making this work? It happens in two steps:

  1. As part of the build process, get the hash key automatically and insert it into the applications info.plist.
  2. Inside your application extract the stored value from the hash key and display it in the about box

Steps to Automatically set the BuildHashKey when building your Application

  1. Open your XCode project.
  2. Under targets select your application.
  3. Right click on the target and choose Add -> New Build Phase -> New Run Script Build Phase, as in:
  4. Change the shell to be /usr/bin/python instead of /bin/sh.
  5. Then in the script, copy and paste the following — I actually did this in bash first but decided to do it properly again in python so that I will be able to read it again in six months time if need be, python being that much more readable :

import os, subprocess, re, sys

targetBuildDir = os.getenv("TARGET_BUILD_DIR") getChangeset = subprocess.Popen('hg parent --template "{node|short}" --cwd ' + targetBuildDir, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)

if (getChangeset.stderr.read() != ""): print "Error in obtaining current changeset of the Mercurial repository" sys.exit(0) # if you want the build to fail here since the changeset is malformed change this to sys.exit(1)

changeset = getChangeset.stdout.read() if (not re.search("^[0-9a-f]{12}$", changeset)): print "Current changeset of the Mercurial repository is malformed" sys.exit(0) # if you want the build to fail here since the changeset is malformed change this to sys.exit(1)

infoPlist = os.path.join(targetBuildDir, "MacHg.app/Contents/Info.plist") if not os.path.exists(infoPlist): print "Cannot locate MacHg.app/Contents/Info.plist" sys.exit(1) # if you want the build to not fail here change this to sys.exit(0)

result = subprocess.Popen('/usr/libexec/PlistBuddy -c "Delete BuildHashKey" ' + infoPlist, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) result = subprocess.Popen('/usr/libexec/PlistBuddy -c "Add BuildHashKey string '+ changeset + '" ' + infoPlist, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)

print "MacHg BuildHashKey set to " + changeset

Of course you need to change MacHg.app to the name of your application. Also you might need to specify the full path to hg (ie /usr/local/bin/hg) in the line:
getChangeset = subprocess.Popen('hg parent --template "{node|short}" --cwd ' + targetBuildDir, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
Also you might want to have the build fail if the changeset is not available, since currently the script above just keeps going.  (I want users who download and compile MacHg to not get lots of critical errors if things are not set up just right.)

Using the BuildHasKey in your Application

Then back in your application you can have a method which will get the hash key from the info.plist:

- (NSString) macHgBuildHashKeyString
{
    NSString key = [[NSBundle mainBundle] objectForInfoDictionaryKey: @"BuildHashKey"];
    return key ? key : @"";
}
Then it’s just a matter of styling it and viola, you have the ingredients for versioning your application with the Mercurial changeset hash key. Actually, after doing this I found out that over at Cocoa is My Girlfriend he had done something similar but in bash.

Leave a Comment

Launched!

Whew! I just launched MacHg 0.9.0 to the public. I opened up the website and bitbucket sources to public viewing, added a google group, updated the sparkle app cast, fixed a few last bugs, synchronized the information now between the website, the bit bucket wiki, and the announcement email, and well launched… Time to go celebrate… Here is the full text of the launch:

Hi All,

I am pleased to announce the initial public release of MacHg. MacHg is a gui client for Mercurial. It runs under OSX 10.6 (Snow leopard). It is free to use and donation ware.

Links

You can get an executable application here: http://jasonfharris.com/machg/downloads/downloads.html

You can view (and clone) the MacHg sources at: http://bitbucket.org/jfh/machg

You can view a screen cast ‘MacHg Introduction’ at: http://jasonfharris.com/machg/screencasts/introduction/screencast_introduction.html

Discussion group about MacHg at: http://groups.google.com/group/machg_mercurial

MacHg Features

  • Document based structure with multiple repositories per document
  • View incoming and outgoing at a glance between compatible repositories
  • Auto refreshes the status of tracked files when they change
  • Incremental loading of history (for efficiency)
  • Works with large repositories (ie for example can load and work with the Mozilla repository which is 3.35Gb)
  • Fully compatible with command line Mercurial (You can make changes on the command line and they are reflected in MacHg.)
  • Fully multi-threaded using Grand Central Dispatch and threading goodness
  • File browser view to work with files
  • History view to explore the changeset history
  • Differences view to explore the historical changes between different revisions
  • Interacting with other repositories: pull, push, incoming, outgoing, clone, etc
  • Contextual menus and shortcuts in many places
  • Diff multiple files at once
  • Renaming, merging, updating, reverting, adding files, removing files, etc
  • Add and remove local tags, global tags, bookmarks, and branches
  • Interface to history editing: collapse, histedit, rebase, strip
  • Importing and exporting of patches
  • Uses the Sparkle framework for “in application” updates

Contributing

If you would like to contribute I would be happy to receive and acknowledge help in a large number of areas, including: - Testing - Documentation (MacHg has some documentation but it would be nice to have a much more complete set of documentation.) - Cocoa coding (Lots of potential enhancements here) - Mercurial extension writing (There are a few extensions I could use help with: for example, around permissibility of dragging and dropping in history rewriting, etc.) - Translating (Especially those who have experience using Apple’s polyglot tool, etc.) - Web designers (There are a number of enhancements to be made to web pages, wikis, etc.) - Graphic design (Icon design, etc.)

Thanks, Jason

Leave a Comment