##// END OF EJS Templates
Simplify StreamCapturer for subprocess testing...
Simplify StreamCapturer for subprocess testing Rather than using a transient pipe for each subprocess started, the StreamCapturer now makes a single pipe, and subprocesses redirect their output to it. So long as this works on Windows (I've done brief testing, and os.pipe() seems to be functional), this will hopefully make this much more robust. The recent failures in ShiningPanda on IPython.parallel have been caused by StreamCapturer.

File last commit:

r13169:ae6ab362
r13405:4ad2c011
Show More
backport_pr.py
159 lines | 4.6 KiB | text/x-python | PythonLexer
MinRK
shebang backport_pr
r8347 #!/usr/bin/env python
MinRK
add backport_pr to tools...
r8346 """
Backport pull requests to a particular branch.
MinRK
add ability to check what PRs should be backported in backport_pr...
r12424 Usage: backport_pr.py branch [PR]
MinRK
add backport_pr to tools...
r8346
e.g.:
MinRK
add ability to check what PRs should be backported in backport_pr...
r12424 python tools/backport_pr.py 0.13.1 123
MinRK
add backport_pr to tools...
r8346
to backport PR #123 onto branch 0.13.1
MinRK
add ability to check what PRs should be backported in backport_pr...
r12424 or
python tools/backport_pr.py 1.x
to see what PRs are marked for backport that have yet to be applied.
MinRK
add backport_pr to tools...
r8346 """
from __future__ import print_function
import os
MinRK
add ability to check what PRs should be backported in backport_pr...
r12424 import re
MinRK
add backport_pr to tools...
r8346 import sys
MinRK
add ability to check what PRs should be backported in backport_pr...
r12424
MinRK
add backport_pr to tools...
r8346 from subprocess import Popen, PIPE, check_call, check_output
from urllib import urlopen
MinRK
add ability to check what PRs should be backported in backport_pr...
r12424 from gh_api import (
get_issues_list,
get_pull_request,
get_pull_request_files,
is_pull_request,
Skipper Seabold
Allow checking for backports via milestone
r13169 get_milestone_id,
MinRK
add ability to check what PRs should be backported in backport_pr...
r12424 )
MinRK
add backport_pr to tools...
r8346
def find_rejects(root='.'):
for dirname, dirs, files in os.walk(root):
for fname in files:
if fname.endswith('.rej'):
yield os.path.join(dirname, fname)
def get_current_branch():
branches = check_output(['git', 'branch'])
for branch in branches.splitlines():
if branch.startswith('*'):
return branch[1:].strip()
def backport_pr(branch, num, project='ipython/ipython'):
current_branch = get_current_branch()
if branch != current_branch:
check_call(['git', 'checkout', branch])
Thomas Kluyver
Update target branch before backporting PR
r12276 check_call(['git', 'pull'])
MinRK
get files list in backport_pr...
r12129 pr = get_pull_request(project, num, auth=True)
files = get_pull_request_files(project, num, auth=True)
MinRK
add backport_pr to tools...
r8346 patch_url = pr['patch_url']
title = pr['title']
description = pr['body']
fname = "PR%i.patch" % num
if os.path.exists(fname):
print("using patch from {fname}".format(**locals()))
with open(fname) as f:
patch = f.read()
else:
req = urlopen(patch_url)
patch = req.read()
Skipper Seabold
Allow checking for backports via milestone
r13169
MinRK
add backport_pr to tools...
r8346 msg = "Backport PR #%i: %s" % (num, title) + '\n\n' + description
check = Popen(['git', 'apply', '--check', '--verbose'], stdin=PIPE)
a,b = check.communicate(patch)
Skipper Seabold
Allow checking for backports via milestone
r13169
MinRK
add backport_pr to tools...
r8346 if check.returncode:
print("patch did not apply, saving to {fname}".format(**locals()))
print("edit {fname} until `cat {fname} | git apply --check` succeeds".format(**locals()))
print("then run tools/backport_pr.py {num} again".format(**locals()))
if not os.path.exists(fname):
with open(fname, 'wb') as f:
f.write(patch)
return 1
Skipper Seabold
Allow checking for backports via milestone
r13169
MinRK
add backport_pr to tools...
r8346 p = Popen(['git', 'apply'], stdin=PIPE)
a,b = p.communicate(patch)
Skipper Seabold
Allow checking for backports via milestone
r13169
MinRK
get files list in backport_pr...
r12129 filenames = [ f['filename'] for f in files ]
MinRK
add backport_pr to tools...
r8346
MinRK
use check_call for git add and commit...
r12341 check_call(['git', 'add'] + filenames)
Skipper Seabold
Allow checking for backports via milestone
r13169
MinRK
use check_call for git add and commit...
r12341 check_call(['git', 'commit', '-m', msg])
Skipper Seabold
Allow checking for backports via milestone
r13169
MinRK
use check_call for git add and commit...
r12341 print("PR #%i applied, with msg:" % num)
print()
print(msg)
print()
Skipper Seabold
Allow checking for backports via milestone
r13169
MinRK
add backport_pr to tools...
r8346 if branch != current_branch:
check_call(['git', 'checkout', current_branch])
Skipper Seabold
Allow checking for backports via milestone
r13169
MinRK
add backport_pr to tools...
r8346 return 0
MinRK
add ability to check what PRs should be backported in backport_pr...
r12424 backport_re = re.compile(r"[Bb]ackport.*?(\d+)")
def already_backported(branch, since_tag=None):
"""return set of PRs that have been backported already"""
if since_tag is None:
since_tag = check_output(['git','describe', branch, '--abbrev=0']).decode('utf8').strip()
cmd = ['git', 'log', '%s..%s' % (since_tag, branch), '--oneline']
lines = check_output(cmd).decode('utf8')
return set(int(num) for num in backport_re.findall(lines))
Skipper Seabold
Allow checking for backports via milestone
r13169 def should_backport(labels=None, milestone=None):
MinRK
add ability to check what PRs should be backported in backport_pr...
r12424 """return set of PRs marked for backport"""
Skipper Seabold
Allow checking for backports via milestone
r13169 if labels is None and milestone is None:
raise ValueError("Specify one of labels or milestone.")
elif labels is not None and milestone is not None:
raise ValueError("Specify only one of labels or milestone.")
if labels is not None:
issues = get_issues_list("ipython/ipython",
labels=labels,
state='closed',
auth=True,
)
else:
milestone_id = get_milestone_id("ipython/ipython", milestone,
auth=True)
issues = get_issues_list("ipython/ipython",
milestone=milestone_id,
state='closed',
auth=True,
)
MinRK
add ability to check what PRs should be backported in backport_pr...
r12424 should_backport = set()
for issue in issues:
if not is_pull_request(issue):
continue
Skipper Seabold
Allow checking for backports via milestone
r13169 pr = get_pull_request("ipython/ipython", issue['number'],
auth=True)
MinRK
add ability to check what PRs should be backported in backport_pr...
r12424 if not pr['merged']:
print ("Marked PR closed without merge: %i" % pr['number'])
continue
should_backport.add(pr['number'])
return should_backport
MinRK
add backport_pr to tools...
r8346 if __name__ == '__main__':
Skipper Seabold
Allow checking for backports via milestone
r13169
MinRK
add ability to check what PRs should be backported in backport_pr...
r12424 if len(sys.argv) < 2:
MinRK
add backport_pr to tools...
r8346 print(__doc__)
sys.exit(1)
Skipper Seabold
Allow checking for backports via milestone
r13169
MinRK
add ability to check what PRs should be backported in backport_pr...
r12424 if len(sys.argv) < 3:
branch = sys.argv[1]
already = already_backported(branch)
MinRK
to-backport label is now 1.2
r12715 should = should_backport("backport-1.2")
MinRK
add ability to check what PRs should be backported in backport_pr...
r12424 print ("The following PRs should be backported:")
for pr in should.difference(already):
print (pr)
sys.exit(0)
Skipper Seabold
Allow checking for backports via milestone
r13169
MinRK
add backport_pr to tools...
r8346 sys.exit(backport_pr(sys.argv[1], int(sys.argv[2])))