blob: d500e094231b76a46ddb4813ed69ee3f2d2297ba [file] [log] [blame]
Søren Gjesse1525df32022-06-30 14:04:44 +02001#!/usr/bin/env python3
2# Copyright (c) 2022, the R8 project authors. Please see the AUTHORS file
3# for details. All rights reserved. Use of this source code is governed by a
4# BSD-style license that can be found in the LICENSE file.
5
6import argparse
7import os
8import subprocess
9import sys
10import utils
11
Ian Zerny33f3d812022-09-06 10:59:05 +020012VERSION_FILE = 'src/main/java/com/android/tools/r8/Version.java'
13VERSION_PREFIX = 'String LABEL = "'
14
Søren Gjesse1525df32022-06-30 14:04:44 +020015
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +020016def parse_options():
17 parser = argparse.ArgumentParser(description='Release r8')
18 parser.add_argument('--branch',
19 metavar=('<branch>'),
20 help='Branch to cherry-pick to')
21 parser.add_argument('--current-checkout',
22 '--current_checkout',
23 default=False,
24 action='store_true',
25 help='Perform cherry picks into the current checkout')
26 parser.add_argument('--no-upload',
27 '--no_upload',
28 default=False,
29 action='store_true',
30 help='Do not upload to Gerrit')
31 parser.add_argument('hashes',
32 metavar='<hash>',
33 nargs='+',
34 help='Hashed to merge')
Søren Gjesse0aa74cd2023-11-15 09:32:23 +010035 parser.add_argument('--remote',
Christoffer Quist Adamsen7daed622023-11-10 11:10:31 +010036 default='origin',
37 help='The remote name (defaults to "origin")')
Søren Gjesse4ce6d8b2024-11-13 11:17:59 +010038 parser.add_argument('--yes',
39 default=False,
40 action='store_true',
41 help='Answer "yes" to all questions')
Søren Gjessee1b18752025-01-13 11:56:52 +010042 parser.add_argument('--reviewer',
43 metavar=('<reviewer(s)>'),
44 default=[],
45 action='append',
46 help='Rewiever(s) for the cherry-pick(s)')
47 parser.add_argument('--send-mail',
48 '--send_mail',
49 default=False,
50 action='store_true',
51 help='Send Gerrit review request right away')
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +020052 return parser.parse_args()
Søren Gjesse1525df32022-06-30 14:04:44 +020053
54
55def run(args):
Christoffer Quist Adamsen7daed622023-11-10 11:10:31 +010056 if args.current_checkout:
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +020057 for i in range(len(args.hashes) + 1):
Christoffer Quist Adamsen7daed622023-11-10 11:10:31 +010058 branch = 'cherry-%s-%d' % (args.branch, i + 1)
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +020059 print('Deleting branch %s' % branch)
60 subprocess.run(['git', 'branch', branch, '-D'])
Søren Gjesse1525df32022-06-30 14:04:44 +020061
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +020062 bugs = set()
Ian Zerny33f3d812022-09-06 10:59:05 +020063
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +020064 count = 1
65 for hash in args.hashes:
Christoffer Quist Adamsen7daed622023-11-10 11:10:31 +010066 branch = 'cherry-%s-%d' % (args.branch, count)
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +020067 print('Cherry-picking %s in %s' % (hash, branch))
Christoffer Quist Adamsen7daed622023-11-10 11:10:31 +010068 if count == 1:
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +020069 subprocess.run([
70 'git', 'new-branch', branch, '--upstream',
Christoffer Quist Adamsen7daed622023-11-10 11:10:31 +010071 '%s/%s' % (args.remote, args.branch)
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +020072 ])
73 else:
74 subprocess.run(['git', 'new-branch', branch, '--upstream-current'])
75
76 subprocess.run(['git', 'cherry-pick', hash])
77 confirm_and_upload(branch, args, bugs)
78 count = count + 1
79
Christoffer Quist Adamsen7daed622023-11-10 11:10:31 +010080 branch = 'cherry-%s-%d' % (args.branch, count)
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +020081 subprocess.run(['git', 'new-branch', branch, '--upstream-current'])
82
83 old_version = 'unknown'
84 for line in open(VERSION_FILE, 'r'):
85 index = line.find(VERSION_PREFIX)
86 if index > 0:
87 index += len(VERSION_PREFIX)
88 subline = line[index:]
89 old_version = subline[:subline.index('"')]
90 break
91
92 new_version = 'unknown'
Søren Gjesseba542a62024-05-31 13:01:09 +020093 if old_version.find('.') > 0 and old_version.find('-') == -1:
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +020094 split_version = old_version.split('.')
95 new_version = '.'.join(split_version[:-1] +
96 [str(int(split_version[-1]) + 1)])
97 subprocess.run([
98 'sed', '-i',
99 's/%s/%s/' % (old_version, new_version), VERSION_FILE
100 ])
Søren Gjesse1525df32022-06-30 14:04:44 +0200101 else:
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200102 editor = os.environ.get('VISUAL')
103 if not editor:
104 editor = os.environ.get('EDITOR')
105 if not editor:
106 editor = 'vi'
Søren Gjessef7997e02024-12-16 10:26:43 +0100107 input("\nCannot automatically determine the new version.\n"
108 + "Press [enter] to edit %s for version update with editor '%s'." %
Søren Gjesseba542a62024-05-31 13:01:09 +0200109 (VERSION_FILE, editor))
110 subprocess.run([editor, VERSION_FILE])
Søren Gjessef7997e02024-12-16 10:26:43 +0100111 new_version = input('Please enter the new version for the commit message: ')
Søren Gjesse1525df32022-06-30 14:04:44 +0200112
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200113 message = ("Version %s\n\n" % new_version)
114 for bug in sorted(bugs):
115 message += 'Bug: b/%s\n' % bug
Søren Gjesse1525df32022-06-30 14:04:44 +0200116
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200117 subprocess.run(['git', 'commit', '-a', '-m', message])
118 confirm_and_upload(branch, args, None)
Søren Gjesse4ce6d8b2024-11-13 11:17:59 +0100119 if not args.current_checkout and not args.yes:
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200120 while True:
121 try:
122 answer = input(
123 "Type 'delete' to finish and delete checkout in %s: " %
124 os.getcwd())
125 if answer == 'delete':
126 break
127 except KeyboardInterrupt:
128 pass
Ian Zerny33f3d812022-09-06 10:59:05 +0200129
Søren Gjesse1525df32022-06-30 14:04:44 +0200130
Søren Gjessee1b18752025-01-13 11:56:52 +0100131def reviewer_arg(reviewer):
132 if reviewer.find('@') == -1:
133 reviewer = reviewer + "@google.com"
134 return '--reviewer=' + reviewer
135
136
Ian Zerny8b9c0af2022-09-07 12:56:03 +0200137def confirm_and_upload(branch, args, bugs):
Søren Gjesse4ce6d8b2024-11-13 11:17:59 +0100138 if not args.yes:
139 question = ('Ready to continue (cwd %s, will not upload to Gerrit)' %
140 os.getcwd() if args.no_upload else
141 'Ready to upload %s (cwd %s)' % (branch, os.getcwd()))
Ian Zerny8b9c0af2022-09-07 12:56:03 +0200142
Søren Gjesse4ce6d8b2024-11-13 11:17:59 +0100143 while True:
144 try:
145 answer = input(question + ' [yes/abort]? ')
146 if answer == 'yes':
147 break
148 if answer == 'abort':
149 print('Aborting new branch for %s' % branch)
150 sys.exit(1)
151 except KeyboardInterrupt:
152 pass
Ian Zerny8b9c0af2022-09-07 12:56:03 +0200153
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200154 # Compute the set of bug refs from the commit message after confirmation.
155 # If done before a conflicting cherry-pick status will potentially include
156 # references that are orthogonal to the pick.
157 if bugs != None:
158 commit_message = subprocess.check_output(
159 ['git', 'log', '--format=%B', '-n', '1', 'HEAD'])
160 commit_lines = [
161 l.strip() for l in commit_message.decode('UTF-8').split('\n')
162 ]
163 for line in commit_lines:
Christoffer Quist Adamsen7daed622023-11-10 11:10:31 +0100164 bug = None
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200165 if line.startswith('Bug: '):
Christoffer Quist Adamsen7daed622023-11-10 11:10:31 +0100166 bug = line.replace('Bug: ', '')
167 elif line.startswith('Fixed: '):
168 bug = line.replace('Fixed: ', '')
169 elif line.startswith('Fixes: '):
170 bug = line.replace('Fixes: ', '')
171 if bug:
172 bugs.add(bug.replace('b/', '').strip())
Ian Zerny8b9c0af2022-09-07 12:56:03 +0200173
Søren Gjessee1b18752025-01-13 11:56:52 +0100174 cmd = ['git', 'cl', 'upload', '--bypass-hooks']
175 if args.yes:
176 cmd.append('-f')
177 if args.reviewer:
178 cmd.extend(map(reviewer_arg, args.reviewer))
179 if args.send_mail:
180 cmd.append('--send-mail')
Christoffer Quist Adamsen7daed622023-11-10 11:10:31 +0100181 if not args.no_upload:
Søren Gjesse4ce6d8b2024-11-13 11:17:59 +0100182 subprocess.run(cmd)
Søren Gjessee1b18752025-01-13 11:56:52 +0100183 else:
184 print('Not uploading, upload command was "%s"' % cmd)
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200185
Ian Zerny33f3d812022-09-06 10:59:05 +0200186
Søren Gjesse1525df32022-06-30 14:04:44 +0200187def main():
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200188 args = parse_options()
Søren Gjesse1525df32022-06-30 14:04:44 +0200189
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200190 if (not args.current_checkout):
191 with utils.TempDir() as temp:
192 print("Performing cherry-picking in %s" % temp)
193 subprocess.check_call(['git', 'clone', utils.REPO_SOURCE, temp])
194 with utils.ChangedWorkingDirectory(temp):
195 run(args)
196 else:
197 # Run in current directory.
198 print("Performing cherry-picking in %s" % os.getcwd())
199 subprocess.check_output(['git', 'fetch', 'origin'])
Søren Gjesse1525df32022-06-30 14:04:44 +0200200 run(args)
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200201
Søren Gjesse1525df32022-06-30 14:04:44 +0200202
203if __name__ == '__main__':
Christoffer Quist Adamsen2434a4d2023-10-16 11:29:03 +0200204 sys.exit(main())