Top Ten (Mercurial) Commands

Since Mercurial took top spot in the top ten commands post, I though it might be interesting to take a look at the break down of which Mercurial sub-commands I end up using:

aaron@ares ~$ history | grep hg | awk '{print $3}' | sort | uniq -c | sort -rn | head
  97 st
  21 commit
  20 push
  14 addremove
   8 diff
   7 qrefresh
   4 qnew
   4 qfinish
   3 up
   3 revert

hg st takes the top spot, indicating that "What the hell have I changed?" is a pretty important question to have answered. The fact that hg commit and hg push are at the top while hg pull is nowhere to be seen is a bit of an anomaly due to the fact that I'm the only one working on the repositories in question. I would expect the results to be very different if you did the same experiment on my work machine. The hg q* are all commands that are part of the Mercurial Queues extension that I use for shaping my changesets and rewriting history.

Extensions

I make pretty heavy use of both the Mercurial Queues and Rebase extensions. In tandem, they give me the ability to make my changesets to be exactly what I want them to be and to move my local branches to tip before I push (which I use so that I don't have to add trivial merge changesets). My workflow has a tendecy to look like this:

$ # do work
$ hg qnew -f -m "A pithy commit message bugzid: 1234567" a_patch.diff
$ hg qpush -a
applying first.diff
now at: first.diff
$ hg pull --rebase
pulling from /a/repository
searching for changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files
$ hg qpop
popping first.diff
now at: a_patch.diff
$ hg qfinish -a
$ hg push
pushing to /a/repository
searching for changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files
$ hg qpush
applying first.diff
now at: first.diff
$ # do more work
$ hg qrefresh
$ hg pull --rebase
pulling from /a/repository
searching for changes
no changes found
$ hg qfinish -a
$ hg push
pushing to /a/repository
searching for changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files

Sure, I could live in the world of hg fetch and type fewer commands, but I feel like having nice atomic changesets, commit messages without typos and a nice clean history is worth the extra typing.

Top Ten Commands (redux)

A few years ago I posted a list of the top ten commands I use gleaned by parsing the output of history. Here's the origional list ca. 2008:

aaron@athena ~$ history | awk '{print $2}' | sort | uniq -c | sort -rn | head
 134 ls
  90 svn
  77 cd
  16 sudo
  15 gvim
  12 rm
  11 script/server
  11 hg
  10 mongrel_rails
   7 slocate

... and here's the new list ca. 2010:

aaron@ares ~$ history | awk '{print $2}' | sort | uniq -c | sort -rn | head
 198 hg
  59 paver
  41 ls
  36 ./blogc
  33 cd
  26 python
  19 gvim
  14 fab
  12 rm
  12 ./dist/sassey

And the winner is...

The big change is that Mercurial has completely replaced Subversion as my version control system of choice. Not only that, but I actually use hg more than I used to use svn. Part of this is that hg is better/faster/easier/more useful than svn and part of it is that I've really gotten in the habit of using Mercurial for everything (which you might argue is a consequence of that first thing ;-).

I've started using Paver and Fabric and they are both awesome. I've stopped using Rails, but I was only really using it for school (My current "web framework" of choice is CherryPy, it is also awesome).

./blogc which takes the number four sport, is one of the new tools that I use to work on my blog.

Other than that, I still use gvim, rm, ls, and cd. Shocking!

Grayvatar

http://aaron.maenpaa.ca/grayvatar/634329486bd326c395c8b3539c035139?s=196&d=identicon&r=PG

The week before last I got to spend some time working on a prototype as part of a sekrit project at work. In order to give the prototype the air of not-quite-done, I did the whole thing in black and white. This worked great up until I added in Identicons to identify users, which added a bunch of brightly colored triangles and ruined the whole black-and-white aesthetic. I eventually ended up pulling a bunch of Identicons from Gravatar with wget and desaturated them with ImageMagik. It worked, but it was kind of gross.

Teh Codez

It occurred to me that it should be pretty straightforward to build a web app that implemented the Gravatar API and desaturate real Gravatars, so I took a crack at it:

import StringIO
import urllib, urllib2

import cherrypy
import Image

from paver.easy import path

URL = "http://www.gravatar.com/avatar/%s?%s"

class Grayvatar(object):
    @cherrypy.expose
    def default(self, *bits, **kwargs):
        if bits:
            cherrypy.response.headers["Content-Type"] = "image/png"
            url = URL % (bits[0], urllib.urlencode(kwargs))
            img = get_img(url).convert("L")
            return img_as_str(img)

        pwd = path(__file__).abspath().parent
        return (pwd / "how_it_works.html").text()

def get_img(url):
    sock = urllib2.urlopen(url)
    return Image.open(StringIO.StringIO(sock.read()))

def img_as_str(img):
    sock = StringIO.StringIO()
    img.save(sock, "png")
    return sock.getvalue()

if __name__ == "__main__":
    cherrypy.quickstart(Grayvatar())

I think it's awesome that, thanks to CherrPy and PIL, I could put together a web app that does all that 30 odd lines (including imports), but it's less awesome that so many of those lines are shuffling data in and out of a StringIO.

mod_wsgi

I set up an instance at: http://aaron.maenpaa.ca/grayvatar using Apache and mod_wsgi. I used a lightly adapted version of the the wsgi config from the CherryPy wiki.

import sys
sys.stdout = sys.stderr

import atexit
import threading
import cherrypy

sys.path = ['/home/aaron/code/grayvatar'] + sys.path

import grayvatar

cherrypy.config.update({
    'environment': 'embedded',
    'log.screen': True,
})

if cherrypy.__version__.startswith('3.0') and cherrypy.engine.state == 0:
    cherrypy.engine.start(blocking=False)
    atexit.register(cherrypy.engine.stop)

application = cherrypy.Application(grayvatar.Grayvatar(), script_name=None)

The most important change was adding 'log.screen': True to the config. This sends errors to stderr, which eventually makes it's way to /var/log/apache2/error.log which makes it possible to figure out what's going on when things don't go right.

How It Works

Just like Gravatar. The base URL is http://aaron.maenpaa.ca/grayvatar/. You calculate the MD5 hash of your email address, append it to the base URL and then add any query parameters that Gravatar supports. That gets you a URL like this: http://aaron.maenpaa.ca/grayvatar/634329486bd326c395c8b3539c035139?s=256&d=identicon&r=PG

It fetchs the appropriate Gravatar, desaturates and returns it. Keep in mind, this is a toy: It doesn't actually respect the cache headers Gravatar sends and worse, it doesn't even pass them along to the client.

Baneslayer-Lifelink

In my post about my Pyromancer's Ascension deck, I mentioned that I was playing against my Baneslayer-Lifelink deck and I thought I'd share the decklist:

This deck came into being as a way to find a home for the Baneslayer Angels that I purchased on the basis that they were too awesome for me to not have a playset. The deck ends up being unified mechanically by lifelink (that's the "Lifelink" part of Baneslayer-Lifelink) even though, thematically, it's a bit unfocused. Angels, and priests, and vampires! Oh my!

It turns out that the Vampire Nighthawks are surprisingly effective. The combination of deathtouch, flying and lifelink make them difficult to block and, conversely, great blockers. They provide great early game attackers to dishearten your opponent as your life total starts going in the "wrong" direction. One of the Grave Titans and the Wurmcoil Engine actually came out of boosters (Shocking, I know) and made their way in to provide some late game heavies.

cat in Sawzall (redux)

After playing with Sawsall a little bit more, I have a slightly better version of cat than the last one I posted:

w: string = input;
emit stdout <- w;

This gets rid of the table and makes the program one whole line shorter :)