From 61aacf0d8dc78d9cab5eea37dd031e9692341de2 2012-06-01 11:42:34 From: Matthias BUSSONNIER Date: 2012-06-01 11:42:34 Subject: [PATCH] merge pull request by number with options : merge PR -m number [number ...] lists pull request (-l) use github v2 (-v2) api (sorry for me i've issues with v3/https/proxy) --- diff --git a/tools/gh_api.py b/tools/gh_api.py index 6b042ed..828592b 100644 --- a/tools/gh_api.py +++ b/tools/gh_api.py @@ -73,8 +73,24 @@ def post_gist(content, description='', filename='file', auth=False): response_data = json.loads(response.text) return response_data['html_url'] -def get_pull_request(project, num): - url = "https://api.github.com/repos/{project}/pulls/{num}".format(project=project, num=num) +def get_pull_request(project, num, httpv2=False): + if httpv2 : + url = "http://github.com/api/v2/json/pulls/{project}/{num}".format(project=project, num=num) + else: + url = "https://api.github.com/repos/{project}/pulls/{num}".format(project=project, num=num) response = requests.get(url) response.raise_for_status() + if httpv2 : + return json.loads(response.text)['pull'] + return json.loads(response.text) + +def get_pulls_list(project,httpv2=False): + if not httpv2 : + url = "https://api.github.com/repos/{project}/pulls".format(project=project) + else : + url = "http://github.com/api/v2/json/pulls/{project}".format(project=project) + response = requests.get(url) + response.raise_for_status() + if httpv2 : + return json.loads(response.text)['pulls'] return json.loads(response.text) diff --git a/tools/git-mpr.py b/tools/git-mpr.py new file mode 100755 index 0000000..9e0ca32 --- /dev/null +++ b/tools/git-mpr.py @@ -0,0 +1,117 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +""" +Usage: + python test_pr.py 1657 +""" +from __future__ import print_function + +import re +import requests +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={} + +def get_branch(repo, branch, owner, mergeable): + 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 + +def merge_pr(num,httpv2=False): + # Get Github authorisation first, so that the user is prompted straight away + # if their login is needed. + + pr = gh_api.get_pull_request(gh_project, num, httpv2) + if(httpv2): + repo = pr['head']['repository']['url'] + owner=pr['head']['user']['name'], + else : + repo=pr['head']['repo']['clone_url'] + owner=pr['head']['repo']['owner']['login'], + + branch=pr['head']['ref'] + mergeable = get_branch(repo=repo, + branch=branch, + owner=owner, + mergeable=pr['mergeable'], + ) + if not mergeable : + cmd = "git pull "+repo+" "+branch + not_merged[str(num)]=cmd + print("==============================================================================") + print("Something went wrong merging this branch, you can try it manually by runngin :") + print(cmd) + print("==============================================================================") + + + +if __name__ == '__main__': + import argparse + 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. + """ + ) + parser.add_argument('-v2','--githubapiv2', action='store_const', const=True) + + 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() + ghv2 = args.githubapiv2 + if(args.list): + pr_list = gh_api.get_pulls_list(gh_project, ghv2) + for pr in pr_list : + mergeable = gh_api.get_pull_request(gh_project, pr['number'],httpv2=ghv2)['mergeable'] + + 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 : + merge_pr(num,httpv2=ghv2) + + 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('*************************************************************************************')