git-mpr.py
136 lines
| 4.4 KiB
| text/x-python
|
PythonLexer
/ tools / git-mpr.py
Matthias BUSSONNIER
|
r7254 | #!/usr/bin/env python | ||
# -*- coding: utf-8 -*- | ||||
""" | ||||
Usage: | ||||
Matthias BUSSONNIER
|
r7448 | python git-mpr.py -m 1657 | ||
Matthias BUSSONNIER
|
r7254 | """ | ||
from __future__ import print_function | ||||
import re | ||||
import requests | ||||
Matthias BUSSONNIER
|
r7448 | import argparse | ||
Matthias BUSSONNIER
|
r7254 | from subprocess import call, check_call, check_output, CalledProcessError | ||
import sys | ||||
import gh_api | ||||
ipy_repository = 'git://github.com/ipython/ipython.git' | ||||
gh_project="ipython/ipython" | ||||
not_merged={} | ||||
Matthias BUSSONNIER
|
r7448 | |||
def merge_branch(repo, branch, owner, mergeable): | ||||
"""try to merge the givent branch into the current one | ||||
If something does not goes smoothly, merge is aborted | ||||
Returns True if merge sucessfull, False otherwise | ||||
""" | ||||
Matthias BUSSONNIER
|
r7254 | merged_branch = "%s-%s" % (owner, branch) | ||
# Delete the branch first | ||||
try : | ||||
check_call(['git', 'pull','--no-edit',repo, branch]) | ||||
except CalledProcessError : | ||||
check_call(['git', 'merge', '--abort']) | ||||
return False | ||||
return True | ||||
Matthias BUSSONNIER
|
r7448 | |||
def merge_pr(num,github_api=3): | ||||
""" try to merge the branch of PR `num` into current branch | ||||
github_api : use github api v2 (to bypass https and issues with proxy) to find the | ||||
remote branch that should be merged by it's number | ||||
""" | ||||
Matthias BUSSONNIER
|
r7254 | # Get Github authorisation first, so that the user is prompted straight away | ||
# if their login is needed. | ||||
Matthias BUSSONNIER
|
r7448 | pr = gh_api.get_pull_request(gh_project, num, github_api) | ||
if github_api == 2: | ||||
Matthias BUSSONNIER
|
r7254 | repo = pr['head']['repository']['url'] | ||
Matthias BUSSONNIER
|
r7448 | owner = pr['head']['user']['name'] | ||
elif github_api == 2 : | ||||
repo = pr['head']['repo']['clone_url'] | ||||
owner = pr['head']['repo']['owner']['login'] | ||||
Matthias BUSSONNIER
|
r7254 | |||
Matthias BUSSONNIER
|
r7448 | branch = pr['head']['ref'] | ||
mergeable = merge_branch(repo=repo, | ||||
Matthias BUSSONNIER
|
r7254 | branch=branch, | ||
owner=owner, | ||||
mergeable=pr['mergeable'], | ||||
) | ||||
if not mergeable : | ||||
cmd = "git pull "+repo+" "+branch | ||||
Matthias BUSSONNIER
|
r7448 | not_merged[str(num)] = cmd | ||
Matthias BUSSONNIER
|
r7254 | print("==============================================================================") | ||
print("Something went wrong merging this branch, you can try it manually by runngin :") | ||||
print(cmd) | ||||
print("==============================================================================") | ||||
Matthias BUSSONNIER
|
r7448 | def main(*args): | ||
Matthias BUSSONNIER
|
r7254 | parser = argparse.ArgumentParser( | ||
description=""" | ||||
Merge (one|many) github pull request by their number.\ | ||||
If pull request can't be merge as is, cancel merge, | ||||
and continue to the next if any. | ||||
""" | ||||
) | ||||
Matthias BUSSONNIER
|
r7448 | parser.add_argument('-v2','--githubapiv2', action='store_const', const=2) | ||
Matthias BUSSONNIER
|
r7254 | |||
grp = parser.add_mutually_exclusive_group() | ||||
grp.add_argument( | ||||
'-l', | ||||
'--list', | ||||
action='store_const', | ||||
const=True, | ||||
help='list PR, their number and their mergeability') | ||||
grp.add_argument('-a', | ||||
'--merge-all', | ||||
action='store_const', | ||||
const=True , | ||||
help='try to merge as many PR as possible, one by one') | ||||
grp.add_argument('-m', | ||||
'--merge', | ||||
type=int, | ||||
help="The pull request numbers", | ||||
nargs='*', | ||||
metavar='pr-number') | ||||
not_merged = {}; | ||||
args = parser.parse_args() | ||||
Matthias BUSSONNIER
|
r7448 | if args.githubapiv2 == 2 : | ||
github_api = 2 | ||||
else : | ||||
github_api = 3 | ||||
Matthias BUSSONNIER
|
r7254 | if(args.list): | ||
Matthias BUSSONNIER
|
r7448 | pr_list = gh_api.get_pulls_list(gh_project, github_api) | ||
Matthias BUSSONNIER
|
r7254 | for pr in pr_list : | ||
Matthias BUSSONNIER
|
r7448 | mergeable = gh_api.get_pull_request(gh_project, pr['number'],github_api=github_api)['mergeable'] | ||
Matthias BUSSONNIER
|
r7254 | |||
ismgb = u"√" if mergeable else " " | ||||
print(u"* #{number} [{ismgb}]: {title}".format( | ||||
number=pr['number'], | ||||
title=pr['title'], | ||||
ismgb=ismgb)) | ||||
if(args.merge_all): | ||||
pr_list = gh_api.get_pulls_list(gh_project) | ||||
for pr in pr_list : | ||||
merge_pr(pr['number']) | ||||
elif args.merge: | ||||
for num in args.merge : | ||||
Matthias BUSSONNIER
|
r7448 | merge_pr(num, github_api=github_api) | ||
Matthias BUSSONNIER
|
r7254 | |||
if not_merged : | ||||
print('*************************************************************************************') | ||||
print('the following branch have not been merged automatically, considere doing it by hand :') | ||||
for num,cmd in not_merged.items() : | ||||
print( "PR {num}: {cmd}".format(num=num,cmd=cmd)) | ||||
print('*************************************************************************************') | ||||
Matthias BUSSONNIER
|
r7448 | |||
if __name__ == '__main__': | ||||
main() | ||||