Skip to content

Commit 3cc998b

Browse files
committed
initial checkin
0 parents  commit 3cc998b

1 file changed

Lines changed: 149 additions & 0 deletions

File tree

git-pull-request

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
#!/usr/bin/env python2.6
2+
3+
"""git pull-request
4+
5+
Automatically check out github pull requests into their own branch
6+
"""
7+
import sys
8+
import getopt
9+
import json
10+
import urllib2
11+
import os
12+
import re
13+
14+
def main():
15+
global repo
16+
17+
# parse command line options
18+
try:
19+
opts, args = getopt.getopt(sys.argv[1:], "h", ["help"])
20+
except getopt.error, msg:
21+
print msg
22+
print "for help use --help"
23+
sys.exit(2)
24+
# process options
25+
for o, a in opts:
26+
if o in ("-h", "--help"):
27+
print __doc__
28+
sys.exit(0)
29+
30+
# get repo name
31+
origin = os.popen('git remote -v').read()
32+
m = re.search('^origin.*?github\.com.*?[:/]([^/]+/[^/]+)\.git\s*\(fetch\)$',origin,re.MULTILINE)
33+
if(m == None or m.group(1) == ''):
34+
print color_text("Failed to determine repo name from origin",'red',True)
35+
repo = m.group(1)
36+
37+
# process arguments
38+
if len(args):
39+
ret = fetch(args[0])
40+
else:
41+
ret = show()
42+
43+
sys.exit(ret)
44+
45+
"""Nicely display info about a given pull request
46+
"""
47+
def display(pr):
48+
if(pr['mergeable']):
49+
conflict = ''
50+
else:
51+
conflict = color_text('*HAS CONFLICTS!*','red',True)
52+
53+
print "%s - %s %s" % (color_text('REQUEST %s' % pr['number'],'green'),pr['title'],conflict)
54+
print " %s" % (color_text(pr['head']['label'],'yellow'))
55+
print " by %s (%s)" % (pr['user']['name'],pr['user']['login'])
56+
print " %s" % (color_text(pr['html_url'],'blue'))
57+
print
58+
59+
60+
"""List open pull requests
61+
62+
Queries the github API for open pull requests in the current repo
63+
"""
64+
def show():
65+
global repo
66+
67+
print "loading open pull requests for %s..." % (repo)
68+
print
69+
url = "http://github.com/api/v2/json/pulls/%s/open" % (repo)
70+
req = urllib2.Request(url)
71+
response = urllib2.urlopen(req)
72+
data = response.read()
73+
if (data == ''):
74+
print "failed to speak with github."
75+
return 3
76+
77+
data = json.loads(data)
78+
#print json.dumps(data,sort_keys=True, indent=4)
79+
80+
for pr in data['pulls']:
81+
display(pr)
82+
return 0
83+
84+
85+
def fetch(pullreq):
86+
global repo
87+
88+
print "loading pull request info for request %s..." % (pullreq)
89+
print
90+
url = "http://github.com/api/v2/json/pulls/%s/%s" % (repo, pullreq)
91+
req = urllib2.Request(url)
92+
response = urllib2.urlopen(req)
93+
data = response.read()
94+
if (data == ''):
95+
print "failed to speak with github."
96+
return 3
97+
98+
data = json.loads(data)
99+
#print json.dumps(data,sort_keys=True, indent=4)
100+
pr = data['pull']
101+
display(pr)
102+
103+
local = 'pull-request-%s' % (pullreq)
104+
branch = os.popen("git branch|grep '^*'|awk '{print $2}'").read().strip();
105+
if(branch != pr['base']['ref'] and branch != local):
106+
print color_text("The pull request is based on branch '%s' but you're on '%s' currently" % \
107+
(pr['base']['ref'], branch),'red',True)
108+
return 4
109+
110+
ret = os.system('git branch %s' % (local));
111+
ret = os.system('git checkout %s' % (local));
112+
if(ret != 0):
113+
print "Failed to create/switch branch"
114+
return 5
115+
116+
print "pulling from %s (%s)" % (pr['head']['repository']['url'], pr['head']['ref']);
117+
118+
ret = os.system('git pull %s %s' % (pr['head']['repository']['url'], pr['head']['ref']));
119+
120+
print
121+
print color_text("done. examine changes and merge into master if good",'green');
122+
123+
return 0
124+
125+
126+
"""Return the given text in ANSI colors
127+
128+
From http://travelingfrontiers.wordpress.com/2010/08/22/how-to-add-colors-to-linux-command-line-output/
129+
"""
130+
def color_text(text, color_name, bold=False):
131+
colors = (
132+
'black', 'red', 'green', 'yellow',
133+
'blue', 'magenta', 'cyan', 'white'
134+
)
135+
136+
if not sys.stdout.isatty():
137+
return text
138+
139+
if color_name in colors:
140+
return '\033[{0};{1}m{2}\033[0m'.format(
141+
int(bold),
142+
colors.index(color_name) + 30,
143+
text)
144+
else:
145+
return text
146+
147+
if __name__ == "__main__":
148+
main()
149+

0 commit comments

Comments
 (0)