diff --git a/git-pull-request b/git-pull-request new file mode 100755 index 0000000..6c40dfa --- /dev/null +++ b/git-pull-request @@ -0,0 +1,148 @@ +#!/usr/bin/env python2.6 + +"""git pull-request + +Automatically check out github pull requests into their own branch +""" +import sys +import getopt +import json +import urllib2 +import os +import re + +def main(): + global repo + + # parse command line options + try: + opts, args = getopt.getopt(sys.argv[1:], "h", ["help"]) + except getopt.error, msg: + print msg + print "for help use --help" + sys.exit(2) + # process options + for o, a in opts: + if o in ("-h", "--help"): + print __doc__ + sys.exit(0) + + # get repo name + origin = os.popen('git remote -v').read() + m = re.search('^origin.*?github\.com.*?[:/]([^/]+/[^/]+)\.git\s*\(fetch\)$',origin,re.MULTILINE) + if(m == None or m.group(1) == ''): + print color_text("Failed to determine repo name from origin",'red',True) + repo = m.group(1) + + # process arguments + if len(args): + ret = fetch(args[0]) + else: + ret = show() + + sys.exit(ret) + +"""Nicely display info about a given pull request +""" +def display(pr): + if(pr['mergeable']): + conflict = '' + else: + conflict = color_text('*HAS CONFLICTS!*','red',True) + + print "%s - %s %s" % (color_text('REQUEST %s' % pr['number'],'green'),pr['title'],conflict) + print " %s" % (color_text(pr['head']['label'],'yellow')) + print " by %s (%s)" % (pr['user']['name'],pr['user']['login']) + print " %s" % (color_text(pr['html_url'],'blue')) + print + + +"""List open pull requests + +Queries the github API for open pull requests in the current repo +""" +def show(): + global repo + + print "loading open pull requests for %s..." % (repo) + print + url = "http://github.com/api/v2/json/pulls/%s/open" % (repo) + req = urllib2.Request(url) + response = urllib2.urlopen(req) + data = response.read() + if (data == ''): + print "failed to speak with github." + return 3 + + data = json.loads(data) + #print json.dumps(data,sort_keys=True, indent=4) + + for pr in data['pulls']: + display(pr) + return 0 + + +def fetch(pullreq): + global repo + + print "loading pull request info for request %s..." % (pullreq) + print + url = "http://github.com/api/v2/json/pulls/%s/%s" % (repo, pullreq) + req = urllib2.Request(url) + response = urllib2.urlopen(req) + data = response.read() + if (data == ''): + print "failed to speak with github." + return 3 + + data = json.loads(data) + #print json.dumps(data,sort_keys=True, indent=4) + pr = data['pull'] + display(pr) + + local = 'pull-request-%s' % (pullreq) + branch = os.popen("git branch|grep '^*'|awk '{print $2}'").read().strip(); + if(branch != pr['base']['ref'] and branch != local): + print color_text("The pull request is based on branch '%s' but you're on '%s' currently" % \ + (pr['base']['ref'], branch),'red',True) + return 4 + + ret = os.system('git branch %s' % (local)); + ret = os.system('git checkout %s' % (local)); + if(ret != 0): + print "Failed to create/switch branch" + return 5 + + print "pulling from %s (%s)" % (pr['head']['repository']['url'], pr['head']['ref']); + + ret = os.system('git pull %s %s' % (pr['head']['repository']['url'], pr['head']['ref'])); + + print + print color_text("done. examine changes and merge into master if good",'green'); + + return 0 + + +"""Return the given text in ANSI colors + +From http://travelingfrontiers.wordpress.com/2010/08/22/how-to-add-colors-to-linux-command-line-output/ +""" +def color_text(text, color_name, bold=False): + colors = ( + 'black', 'red', 'green', 'yellow', + 'blue', 'magenta', 'cyan', 'white' + ) + + if not sys.stdout.isatty(): + return text + + if color_name in colors: + return '\033[{0};{1}m{2}\033[0m'.format( + int(bold), + colors.index(color_name) + 30, + text) + else: + return text + +if __name__ == "__main__": + main()