Main Contents

Grabbing git patches via gmail

Code

I’m a rabid gmail user. I pretty much funnel every piece of email I get from my various email addresses into google. Yes, I drank the kool-aide(tm). What’s it you ya? Wanna fight about it?

Anyhoo, I wanted a system where I could use all of the goodness of git-am without having to actually use something other than my beloved gmail. So, using a little python, libgmail and a hacked up “archive.py” script that came with libgmail, I set out to do what I wanted. I am on a Mac, so I do get the added benefit of having all that unix email goodness built right in.

The basic idea is simple. When a patch comes in that I care about, I tag it with “Patches” in gmail. Then I drop to command line and run this script. It basically logs in to gmail, looks for any messages tagged as “Patches” and copies them to my local (and usually unused) unix user’s inbox. It then removes the “Patches” tag and adds the “Old Patches” tag.

The script looks like so:

#!/usr/bin/env python
#
# Grab email from a gmail label, load it into your local inbox, and
# change the label to something else.
#
# Author: ted@tedkulp.com
# Based on code by: follower@myrealbox.com
#
# License: GPL 2.0
#
import os
import sys
import logging
import time
import datetime
 
# Allow us to run using installed `libgmail` or the one in parent directory.
try:
	 import libgmail
	 logging.warn("Note: Using currently installed `libgmail` version.")
except ImportError:
	 # Urghhh...
	 sys.path.insert(1, os.path.realpath(os.path.join(os.path.dirname(__file__),os.path.pardir)))
 
if __name__ == "__main__":
	import libgmail
	import sys
	from getpass import getpass
 
	username = 'username'
	password = 'password'
	new_label = 'Patches'
	old_label = 'Old Patches'
	mbox_dir = '/var/mail/tedkulp' #Change to inbox for your user
 
	ga = libgmail.GmailAccount(username, password)
 
	print "\nPlease wait, logging in..."
 
	try:
		ga.login()
	except libgmail.GmailLoginFailure:
		print "\nLogin failed. (Wrong username/password?)"
	else:
		print "Log in successful.\n"
 
	result = ga.getMessagesByLabel(new_label, True)
	print
	mbox = []
 
	if len(result):
		for thread in reversed(result):
			print
			print thread.id, len(thread), thread.subject
 
			for msg in reversed(thread):
				print "	 ", msg.id, msg.number, msg.subject
				source = msg.source.replace("\r","").lstrip()
				mbox.append(datetime.datetime.now().strftime("From - %a %b %d %H:%m:%S %Y\n"))
				mbox.append(source)
				mbox.append("\n\n") #TODO:Check if we need either/both?
 
			thread.removeLabel(new_label)
			thread.addLabel(old_label)
 
		open(mbox_dir, "a").writelines(mbox)
 
	else:
		print "No threads found in `%s`." % new_label

And then just like Linus does on http://www.kernel.org/pub/software/scm/git/docs/everyday.html, I can do stuff like:

$ mailx
& s 2 3 4 5 ./+to-apply
& d 2-5
& q
$ git checkout -b topic/one master
$ git am -3 -i -s -u ./+to-apply

Beautiful.

Edit

05/20/2008 - I’ve updated the code a bit. There was a nesting issue that was causing messages to be pulled multiple times. I’ve also added the current date at the time of the pull instead of the 1998 date, and also pulling them in opposite order so that they are pushed into the inbox in the order they were received.

Ted @ May 8, 2008

Leave a comment

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>


Feed