##// END OF EJS Templates
use check_call for git add and commit...
MinRK -
Show More
@@ -1,100 +1,92 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 """
2 """
3 Backport pull requests to a particular branch.
3 Backport pull requests to a particular branch.
4
4
5 Usage: backport_pr.py branch PR
5 Usage: backport_pr.py branch PR
6
6
7 e.g.:
7 e.g.:
8
8
9 backport_pr.py 0.13.1 123
9 backport_pr.py 0.13.1 123
10
10
11 to backport PR #123 onto branch 0.13.1
11 to backport PR #123 onto branch 0.13.1
12
12
13 """
13 """
14
14
15 from __future__ import print_function
15 from __future__ import print_function
16
16
17 import os
17 import os
18 import sys
18 import sys
19 from subprocess import Popen, PIPE, check_call, check_output
19 from subprocess import Popen, PIPE, check_call, check_output
20 from urllib import urlopen
20 from urllib import urlopen
21
21
22 from gh_api import get_pull_request, get_pull_request_files
22 from gh_api import get_pull_request, get_pull_request_files
23
23
24 def find_rejects(root='.'):
24 def find_rejects(root='.'):
25 for dirname, dirs, files in os.walk(root):
25 for dirname, dirs, files in os.walk(root):
26 for fname in files:
26 for fname in files:
27 if fname.endswith('.rej'):
27 if fname.endswith('.rej'):
28 yield os.path.join(dirname, fname)
28 yield os.path.join(dirname, fname)
29
29
30 def get_current_branch():
30 def get_current_branch():
31 branches = check_output(['git', 'branch'])
31 branches = check_output(['git', 'branch'])
32 for branch in branches.splitlines():
32 for branch in branches.splitlines():
33 if branch.startswith('*'):
33 if branch.startswith('*'):
34 return branch[1:].strip()
34 return branch[1:].strip()
35
35
36 def backport_pr(branch, num, project='ipython/ipython'):
36 def backport_pr(branch, num, project='ipython/ipython'):
37 current_branch = get_current_branch()
37 current_branch = get_current_branch()
38 if branch != current_branch:
38 if branch != current_branch:
39 check_call(['git', 'checkout', branch])
39 check_call(['git', 'checkout', branch])
40 check_call(['git', 'pull'])
40 check_call(['git', 'pull'])
41 pr = get_pull_request(project, num, auth=True)
41 pr = get_pull_request(project, num, auth=True)
42 files = get_pull_request_files(project, num, auth=True)
42 files = get_pull_request_files(project, num, auth=True)
43 patch_url = pr['patch_url']
43 patch_url = pr['patch_url']
44 title = pr['title']
44 title = pr['title']
45 description = pr['body']
45 description = pr['body']
46 fname = "PR%i.patch" % num
46 fname = "PR%i.patch" % num
47 if os.path.exists(fname):
47 if os.path.exists(fname):
48 print("using patch from {fname}".format(**locals()))
48 print("using patch from {fname}".format(**locals()))
49 with open(fname) as f:
49 with open(fname) as f:
50 patch = f.read()
50 patch = f.read()
51 else:
51 else:
52 req = urlopen(patch_url)
52 req = urlopen(patch_url)
53 patch = req.read()
53 patch = req.read()
54
54
55 msg = "Backport PR #%i: %s" % (num, title) + '\n\n' + description
55 msg = "Backport PR #%i: %s" % (num, title) + '\n\n' + description
56 check = Popen(['git', 'apply', '--check', '--verbose'], stdin=PIPE)
56 check = Popen(['git', 'apply', '--check', '--verbose'], stdin=PIPE)
57 a,b = check.communicate(patch)
57 a,b = check.communicate(patch)
58
58
59 if check.returncode:
59 if check.returncode:
60 print("patch did not apply, saving to {fname}".format(**locals()))
60 print("patch did not apply, saving to {fname}".format(**locals()))
61 print("edit {fname} until `cat {fname} | git apply --check` succeeds".format(**locals()))
61 print("edit {fname} until `cat {fname} | git apply --check` succeeds".format(**locals()))
62 print("then run tools/backport_pr.py {num} again".format(**locals()))
62 print("then run tools/backport_pr.py {num} again".format(**locals()))
63 if not os.path.exists(fname):
63 if not os.path.exists(fname):
64 with open(fname, 'wb') as f:
64 with open(fname, 'wb') as f:
65 f.write(patch)
65 f.write(patch)
66 return 1
66 return 1
67
67
68 p = Popen(['git', 'apply'], stdin=PIPE)
68 p = Popen(['git', 'apply'], stdin=PIPE)
69 a,b = p.communicate(patch)
69 a,b = p.communicate(patch)
70
70
71 filenames = [ f['filename'] for f in files ]
71 filenames = [ f['filename'] for f in files ]
72
72
73 add = Popen(['git', 'add'] + filenames)
73 check_call(['git', 'add'] + filenames)
74 add.wait()
74
75 if add.returncode:
75 check_call(['git', 'commit', '-m', msg])
76 print("add failed!")
76
77 return 1
77 print("PR #%i applied, with msg:" % num)
78
78 print()
79 commit = Popen(['git', 'commit', '-m', msg])
79 print(msg)
80 commit.wait()
80 print()
81 if commit.returncode:
82 print("commit failed!")
83 return 1
84 else:
85 print("PR #%i applied, with msg:" % num)
86 print()
87 print(msg)
88 print()
89
81
90 if branch != current_branch:
82 if branch != current_branch:
91 check_call(['git', 'checkout', current_branch])
83 check_call(['git', 'checkout', current_branch])
92
84
93 return 0
85 return 0
94
86
95 if __name__ == '__main__':
87 if __name__ == '__main__':
96 if len(sys.argv) < 3:
88 if len(sys.argv) < 3:
97 print(__doc__)
89 print(__doc__)
98 sys.exit(1)
90 sys.exit(1)
99
91
100 sys.exit(backport_pr(sys.argv[1], int(sys.argv[2])))
92 sys.exit(backport_pr(sys.argv[1], int(sys.argv[2])))
General Comments 0
You need to be logged in to leave comments. Login now