#!/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()
