git-mpr.py
127 lines
| 4.0 KiB
| text/x-python
|
PythonLexer
/ tools / git-mpr.py
Matthias BUSSONNIER
|
r7254 | #!/usr/bin/env python | ||
# -*- coding: utf-8 -*- | ||||
""" | ||||
Usage: | ||||
Fernando Perez
|
r10749 | git-mpr [-h] [-l | -a] [pr-number [pr-number ...]] | ||
Type `git mpr -h` for details. | ||||
Matthias BUSSONNIER
|
r7254 | """ | ||
Fernando Perez
|
r10749 | |||
Matthias BUSSONNIER
|
r7254 | |||
Matthias BUSSONNIER
|
r8030 | import io, os | ||
Matthias BUSSONNIER
|
r7448 | import argparse | ||
Matthias BUSSONNIER
|
r7457 | from subprocess import check_call, CalledProcessError | ||
Matthias BUSSONNIER
|
r7254 | |||
import gh_api | ||||
ipy_repository = 'git://github.com/ipython/ipython.git' | ||||
Matthias BUSSONNIER
|
r7457 | gh_project = "ipython/ipython" | ||
not_merged = {} | ||||
Matthias BUSSONNIER
|
r7254 | |||
Matthias BUSSONNIER
|
r7457 | def merge_branch(repo, branch ): | ||
Matthias BUSSONNIER
|
r7448 | """try to merge the givent branch into the current one | ||
If something does not goes smoothly, merge is aborted | ||||
luzpaz
|
r24084 | Returns True if merge successful, False otherwise | ||
Matthias BUSSONNIER
|
r7448 | """ | ||
Matthias BUSSONNIER
|
r7254 | # Delete the branch first | ||
try : | ||||
Matthias BUSSONNIER
|
r8030 | check_call(['git', 'pull', repo, branch], stdin=io.open(os.devnull)) | ||
Matthias BUSSONNIER
|
r7254 | except CalledProcessError : | ||
check_call(['git', 'merge', '--abort']) | ||||
return False | ||||
return True | ||||
Fernando Perez
|
r10749 | |||
def git_new_branch(name): | ||||
"""Create a new branch with the given name and check it out. | ||||
""" | ||||
check_call(['git', 'checkout', '-b', name]) | ||||
Matthias BUSSONNIER
|
r7448 | |||
Fernando Perez
|
r10749 | |||
Matthias BUSSONNIER
|
r7927 | def merge_pr(num): | ||
Matthias BUSSONNIER
|
r7448 | """ try to merge the branch of PR `num` into current branch | ||
""" | ||||
Matthias BUSSONNIER
|
r7254 | # Get Github authorisation first, so that the user is prompted straight away | ||
# if their login is needed. | ||||
Matthias BUSSONNIER
|
r7927 | pr = gh_api.get_pull_request(gh_project, num) | ||
repo = pr['head']['repo']['clone_url'] | ||||
Matthias BUSSONNIER
|
r7254 | |||
Matthias BUSSONNIER
|
r7450 | |||
Matthias BUSSONNIER
|
r7448 | branch = pr['head']['ref'] | ||
mergeable = merge_branch(repo=repo, | ||||
Matthias BUSSONNIER
|
r7254 | branch=branch, | ||
) | ||||
if not mergeable : | ||||
cmd = "git pull "+repo+" "+branch | ||||
Matthias BUSSONNIER
|
r7448 | not_merged[str(num)] = cmd | ||
Matthias BUSSONNIER
|
r7254 | print("==============================================================================") | ||
apunisal
|
r24382 | print("Something went wrong merging this branch, you can try it manually by running :") | ||
Matthias BUSSONNIER
|
r7254 | print(cmd) | ||
print("==============================================================================") | ||||
Matthias BUSSONNIER
|
r7448 | def main(*args): | ||
Matthias BUSSONNIER
|
r7254 | parser = argparse.ArgumentParser( | ||
description=""" | ||||
Matthias BUSSONNIER
|
r8045 | Merge one or more github pull requests by their number. If any | ||
one pull request can't be merged as is, its merge is ignored | ||||
and the process continues with the next ones (if any). | ||||
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') | ||||
Bussonnier Matthias
|
r8144 | parser.add_argument('merge', | ||
Matthias BUSSONNIER
|
r7254 | type=int, | ||
help="The pull request numbers", | ||||
nargs='*', | ||||
metavar='pr-number') | ||||
args = parser.parse_args() | ||||
Matthias BUSSONNIER
|
r7448 | |||
Matthias BUSSONNIER
|
r7254 | if(args.list): | ||
Matthias BUSSONNIER
|
r7927 | pr_list = gh_api.get_pulls_list(gh_project) | ||
Matthias BUSSONNIER
|
r7254 | for pr in pr_list : | ||
Matthias BUSSONNIER
|
r7927 | mergeable = gh_api.get_pull_request(gh_project, pr['number'])['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): | ||||
Fernando Perez
|
r10749 | branch_name = 'merge-' + '-'.join(str(pr['number']) for pr in pr_list) | ||
git_new_branch(branch_name) | ||||
Matthias BUSSONNIER
|
r7254 | pr_list = gh_api.get_pulls_list(gh_project) | ||
for pr in pr_list : | ||||
merge_pr(pr['number']) | ||||
elif args.merge: | ||||
Fernando Perez
|
r10749 | branch_name = 'merge-' + '-'.join(map(str, args.merge)) | ||
git_new_branch(branch_name) | ||||
Matthias BUSSONNIER
|
r7254 | for num in args.merge : | ||
Matthias BUSSONNIER
|
r7927 | merge_pr(num) | ||
Matthias BUSSONNIER
|
r7254 | |||
if not_merged : | ||||
print('*************************************************************************************') | ||||
luz.paz
|
r24322 | print('The following branch has not been merged automatically, consider doing it by hand :') | ||
Matthias BUSSONNIER
|
r7457 | for num, cmd in not_merged.items() : | ||
print( "PR {num}: {cmd}".format(num=num, cmd=cmd)) | ||||
Matthias BUSSONNIER
|
r7254 | print('*************************************************************************************') | ||
Matthias BUSSONNIER
|
r7448 | |||
if __name__ == '__main__': | ||||
main() | ||||